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/20 16:47:00 UTC

[mynewt-nimble] branch freertos-port updated (c1b8508 -> f1dba08)

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

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


 discard c1b8508  porting: Add FreeRTOS port (based on nRF5 SDK)
 discard 2dbba4c  [wip] temporary fixes for controller build
 discard 4b89452  Add copy of hw/drivers/nimble (for controller build)
 discard e284043  Add local copy of Tinycrypt
     add cb8b42c  nimble: Make this proper external repository
     add 33c05c1  Add readme
     new 359188d  Add local copy of Tinycrypt
     new c07f163  Add copy of hw/drivers/nimble (for controller build)
     new b27c0f4  [wip] temporary fixes for controller build
     new f1dba08  porting: Add FreeRTOS port (based on nRF5 SDK)

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (c1b8508)
            \
             N -- N -- N   refs/heads/freertos-port (f1dba08)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 README.md                                     | 71 +++++++++++++++++++++++++++
 nimble/controller/pkg.yml                     |  6 +--
 nimble/controller/test/pkg.yml                | 14 +++---
 nimble/host/mesh/pkg.yml                      | 12 ++---
 nimble/host/pkg.yml                           | 16 +++---
 nimble/host/services/ans/pkg.yml              |  4 +-
 nimble/host/services/bleuart/pkg.yml          |  6 +--
 nimble/host/services/gap/pkg.yml              |  4 +-
 nimble/host/services/gatt/pkg.yml             |  4 +-
 nimble/host/services/ias/pkg.yml              |  4 +-
 nimble/host/services/lls/pkg.yml              |  4 +-
 nimble/host/services/tps/pkg.yml              |  4 +-
 nimble/host/store/config/pkg.yml              |  8 +--
 nimble/host/store/ram/pkg.yml                 |  4 +-
 nimble/host/test/pkg.yml                      | 16 +++---
 nimble/host/util/pkg.yml                      |  4 +-
 nimble/pkg.yml                                |  4 +-
 nimble/transport/emspi/pkg.yml                |  6 +--
 nimble/transport/ram/pkg.yml                  |  6 +--
 nimble/transport/socket/pkg.yml               | 10 ++--
 nimble/transport/uart/pkg.yml                 | 10 ++--
 nimble/host/util/syscfg.yml => repository.yml | 11 ++++-
 22 files changed, 153 insertions(+), 75 deletions(-)
 create mode 100644 README.md
 copy nimble/host/util/syscfg.yml => repository.yml (83%)

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

[mynewt-nimble] 02/04: Add copy of hw/drivers/nimble (for controller build)

Posted by an...@apache.org.
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 c07f16332314a619800acfe9758cc22617057c28
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Mon Dec 18 12:13:35 2017 +0100

    Add copy of hw/drivers/nimble (for controller build)
---
 nimble/drivers/native/include/ble/xcvr.h |   46 +
 nimble/drivers/native/pkg.yml            |   30 +
 nimble/drivers/native/src/ble_hw.c       |  239 ++++
 nimble/drivers/native/src/ble_phy.c      |  632 ++++++++++
 nimble/drivers/nrf51/include/ble/xcvr.h  |   48 +
 nimble/drivers/nrf51/pkg.yml             |   31 +
 nimble/drivers/nrf51/src/ble_hw.c        |  482 ++++++++
 nimble/drivers/nrf51/src/ble_phy.c       | 1494 ++++++++++++++++++++++++
 nimble/drivers/nrf52/include/ble/xcvr.h  |   52 +
 nimble/drivers/nrf52/pkg.yml             |   31 +
 nimble/drivers/nrf52/src/ble_hw.c        |  486 ++++++++
 nimble/drivers/nrf52/src/ble_phy.c       | 1839 ++++++++++++++++++++++++++++++
 nimble/drivers/nrf52/syscfg.yml          |   54 +
 13 files changed, 5464 insertions(+)

diff --git a/nimble/drivers/native/include/ble/xcvr.h b/nimble/drivers/native/include/ble/xcvr.h
new file mode 100644
index 0000000..04741dd
--- /dev/null
+++ b/nimble/drivers/native/include/ble/xcvr.h
@@ -0,0 +1,46 @@
+/*
+ * 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_BLE_XCVR_
+#define H_BLE_XCVR_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Transceiver specific defintions */
+#define XCVR_RX_START_DELAY_USECS     (140)
+#define XCVR_TX_START_DELAY_USECS     (140)
+#define XCVR_PROC_DELAY_USECS         (100)
+#define XCVR_TX_SCHED_DELAY_USECS     \
+    (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+#define XCVR_RX_SCHED_DELAY_USECS     \
+    (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+
+/*
+ * Define HW whitelist size. This is the total possible whitelist size;
+ * not necessarily the size that will be used (may be smaller)
+ */
+#define BLE_HW_WHITE_LIST_SIZE        (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_BLE_XCVR_ */
diff --git a/nimble/drivers/native/pkg.yml b/nimble/drivers/native/pkg.yml
new file mode 100644
index 0000000..f57af62
--- /dev/null
+++ b/nimble/drivers/native/pkg.yml
@@ -0,0 +1,30 @@
+#
+# 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.
+#
+
+pkg.name: hw/drivers/nimble/native
+pkg.description: BLE driver for simulations.
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - ble
+    - bluetooth
+
+pkg.apis: ble_driver
+pkg.deps:
+    - net/nimble/controller
diff --git a/nimble/drivers/native/src/ble_hw.c b/nimble/drivers/native/src/ble_hw.c
new file mode 100644
index 0000000..aa50466
--- /dev/null
+++ b/nimble/drivers/native/src/ble_hw.c
@@ -0,0 +1,239 @@
+/*
+ * 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 <stdint.h>
+#include <assert.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "controller/ble_hw.h"
+
+/* Total number of white list elements supported by nrf52 */
+#define BLE_HW_WHITE_LIST_SIZE      (0)
+
+/* We use this to keep track of which entries are set to valid addresses */
+static uint8_t g_ble_hw_whitelist_mask;
+
+/* Returns public device address or -1 if not present */
+int
+ble_hw_get_public_addr(ble_addr_t *addr)
+{
+    return -1;
+}
+
+/* Returns random static address or -1 if not present */
+int
+ble_hw_get_static_addr(ble_addr_t *addr)
+{
+    return -1;
+}
+
+/**
+ * Clear the whitelist
+ *
+ * @return int
+ */
+void
+ble_hw_whitelist_clear(void)
+{
+    g_ble_hw_whitelist_mask = 0;
+}
+
+/**
+ * Add a device to the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
+{
+    return BLE_ERR_MEM_CAPACITY;
+}
+
+/**
+ * Remove a device from the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ */
+void
+ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
+{
+    return;
+}
+
+/**
+ * Returns the size of the whitelist in HW
+ *
+ * @return int Number of devices allowed in whitelist
+ */
+uint8_t
+ble_hw_whitelist_size(void)
+{
+    return BLE_HW_WHITE_LIST_SIZE;
+}
+
+/**
+ * Enable the whitelisted devices
+ */
+void
+ble_hw_whitelist_enable(void)
+{
+    return;
+}
+
+/**
+ * Disables the whitelisted devices
+ */
+void
+ble_hw_whitelist_disable(void)
+{
+    return;
+}
+
+/**
+ * Boolean function which returns true ('1') if there is a match on the
+ * whitelist.
+ *
+ * @return int
+ */
+int
+ble_hw_whitelist_match(void)
+{
+    return 0;
+}
+
+/* Encrypt data */
+int
+ble_hw_encrypt_block(struct ble_encryption_block *ecb)
+{
+    return -1;
+}
+
+/**
+ * Initialize the random number generator
+ *
+ * @param cb
+ * @param bias
+ *
+ * @return int
+ */
+int
+ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
+{
+    return -1;
+}
+
+/**
+ * Start the random number generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_start(void)
+{
+    return -1;
+}
+
+/**
+ * Stop the random generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_stop(void)
+{
+    return -1;
+}
+
+/**
+ * Read the random number generator.
+ *
+ * @return uint8_t
+ */
+uint8_t
+ble_hw_rng_read(void)
+{
+    return 0;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+/**
+ * Clear the resolving list
+ *
+ * @return int
+ */
+void
+ble_hw_resolv_list_clear(void)
+{
+}
+
+/**
+ * Add a device to the hw resolving list
+ *
+ * @param irk   Pointer to IRK to add
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_resolv_list_add(uint8_t *irk)
+{
+    return BLE_ERR_MEM_CAPACITY;
+}
+
+/**
+ * Remove a device from the hw resolving list
+ *
+ * @param index Index of IRK to remove
+ */
+void
+ble_hw_resolv_list_rmv(int index)
+{
+}
+
+/**
+ * Returns the size of the resolving list. NOTE: this returns the maximum
+ * allowable entries in the HW. Configuration options may limit this.
+ *
+ * @return int Number of devices allowed in resolving list
+ */
+uint8_t
+ble_hw_resolv_list_size(void)
+{
+    return 0;
+}
+
+/**
+ * Called to determine if the address received was resolved.
+ *
+ * @return int  Negative values indicate unresolved address; positive values
+ *              indicate index in resolving list of resolved address.
+ */
+int
+ble_hw_resolv_list_match(void)
+{
+    return -1;
+}
+#endif
diff --git a/nimble/drivers/native/src/ble_phy.c b/nimble/drivers/native/src/ble_phy.c
new file mode 100644
index 0000000..2333eb4
--- /dev/null
+++ b/nimble/drivers/native/src/ble_phy.c
@@ -0,0 +1,632 @@
+/*
+ * 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 <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "ble/xcvr.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "controller/ble_phy.h"
+#include "controller/ble_ll.h"
+
+/* BLE PHY data structure */
+struct ble_phy_obj
+{
+    uint8_t phy_stats_initialized;
+    int8_t  phy_txpwr_dbm;
+    uint8_t phy_chan;
+    uint8_t phy_state;
+    uint8_t phy_transition;
+    uint8_t phy_rx_started;
+    uint8_t phy_encrypted;
+    uint8_t phy_privacy;
+    uint8_t phy_tx_pyld_len;
+    uint32_t phy_aar_scratch;
+    uint32_t phy_access_address;
+    struct ble_mbuf_hdr rxhdr;
+    void *txend_arg;
+    uint8_t *rxdptr;
+    ble_phy_tx_end_func txend_cb;
+};
+struct ble_phy_obj g_ble_phy_data;
+
+/* Statistics */
+struct ble_phy_statistics
+{
+    uint32_t tx_good;
+    uint32_t tx_fail;
+    uint32_t tx_late;
+    uint32_t tx_bytes;
+    uint32_t rx_starts;
+    uint32_t rx_aborts;
+    uint32_t rx_valid;
+    uint32_t rx_crc_err;
+    uint32_t phy_isrs;
+    uint32_t radio_state_errs;
+    uint32_t no_bufs;
+};
+
+struct ble_phy_statistics g_ble_phy_stats;
+
+/* XCVR object to emulate transceiver */
+struct xcvr_data
+{
+    uint32_t irq_status;
+};
+static struct xcvr_data g_xcvr_data;
+
+#define BLE_XCVR_IRQ_F_RX_START     (0x00000001)
+#define BLE_XCVR_IRQ_F_RX_END       (0x00000002)
+#define BLE_XCVR_IRQ_F_TX_START     (0x00000004)
+#define BLE_XCVR_IRQ_F_TX_END       (0x00000008)
+#define BLE_XCVR_IRQ_F_BYTE_CNTR    (0x00000010)
+
+/* "Rail" power level if outside supported range */
+#define BLE_XCVR_TX_PWR_MAX_DBM     (30)
+#define BLE_XCVR_TX_PWR_MIN_DBM     (-20)
+
+/* Statistics */
+STATS_SECT_START(ble_phy_stats)
+    STATS_SECT_ENTRY(phy_isrs)
+    STATS_SECT_ENTRY(tx_good)
+    STATS_SECT_ENTRY(tx_fail)
+    STATS_SECT_ENTRY(tx_late)
+    STATS_SECT_ENTRY(tx_bytes)
+    STATS_SECT_ENTRY(rx_starts)
+    STATS_SECT_ENTRY(rx_aborts)
+    STATS_SECT_ENTRY(rx_valid)
+    STATS_SECT_ENTRY(rx_crc_err)
+    STATS_SECT_ENTRY(rx_late)
+    STATS_SECT_ENTRY(no_bufs)
+    STATS_SECT_ENTRY(radio_state_errs)
+    STATS_SECT_ENTRY(rx_hw_err)
+    STATS_SECT_ENTRY(tx_hw_err)
+STATS_SECT_END
+STATS_SECT_DECL(ble_phy_stats) ble_phy_stats;
+
+STATS_NAME_START(ble_phy_stats)
+    STATS_NAME(ble_phy_stats, phy_isrs)
+    STATS_NAME(ble_phy_stats, tx_good)
+    STATS_NAME(ble_phy_stats, tx_fail)
+    STATS_NAME(ble_phy_stats, tx_late)
+    STATS_NAME(ble_phy_stats, tx_bytes)
+    STATS_NAME(ble_phy_stats, rx_starts)
+    STATS_NAME(ble_phy_stats, rx_aborts)
+    STATS_NAME(ble_phy_stats, rx_valid)
+    STATS_NAME(ble_phy_stats, rx_crc_err)
+    STATS_NAME(ble_phy_stats, rx_late)
+    STATS_NAME(ble_phy_stats, no_bufs)
+    STATS_NAME(ble_phy_stats, radio_state_errs)
+    STATS_NAME(ble_phy_stats, rx_hw_err)
+    STATS_NAME(ble_phy_stats, tx_hw_err)
+STATS_NAME_END(ble_phy_stats)
+
+/* XXX: TODO:
+
+ * 1) Test the following to make sure it works: suppose an event is already
+ * set to 1 and the interrupt is not enabled. What happens if you enable the
+ * interrupt with the event bit already set to 1
+ * 2) how to deal with interrupts?
+ */
+static uint32_t
+ble_xcvr_get_irq_status(void)
+{
+    return g_xcvr_data.irq_status;
+}
+
+static void
+ble_xcvr_clear_irq(uint32_t mask)
+{
+    g_xcvr_data.irq_status &= ~mask;
+}
+
+/**
+ * Copies the data from the phy receive buffer into a mbuf chain.
+ *
+ * @param dptr Pointer to receive buffer
+ * @param rxpdu Pointer to already allocated mbuf chain
+ *
+ * NOTE: the packet header already has the total mbuf length in it. The
+ * lengths of the individual mbufs are not set prior to calling.
+ *
+ */
+void
+ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
+{
+    uint16_t rem_bytes;
+    uint16_t mb_bytes;
+    uint16_t copylen;
+    uint32_t *dst;
+    uint32_t *src;
+    struct os_mbuf *m;
+    struct ble_mbuf_hdr *ble_hdr;
+    struct os_mbuf_pkthdr *pkthdr;
+
+    /* Better be aligned */
+    assert(((uint32_t)dptr & 3) == 0);
+
+    pkthdr = OS_MBUF_PKTHDR(rxpdu);
+    rem_bytes = pkthdr->omp_len;
+
+    /* Fill in the mbuf pkthdr first. */
+    dst = (uint32_t *)(rxpdu->om_data);
+    src = (uint32_t *)dptr;
+
+    mb_bytes = (rxpdu->om_omp->omp_databuf_len - rxpdu->om_pkthdr_len - 4);
+    copylen = min(mb_bytes, rem_bytes);
+    copylen &= 0xFFFC;
+    rem_bytes -= copylen;
+    mb_bytes -= copylen;
+    rxpdu->om_len = copylen;
+    while (copylen > 0) {
+        *dst = *src;
+        ++dst;
+        ++src;
+        copylen -= 4;
+    }
+
+    /* Copy remaining bytes */
+    m = rxpdu;
+    while (rem_bytes > 0) {
+        /* If there are enough bytes in the mbuf, copy them and leave */
+        if (rem_bytes <= mb_bytes) {
+            memcpy(m->om_data + m->om_len, src, rem_bytes);
+            m->om_len += rem_bytes;
+            break;
+        }
+
+        m = SLIST_NEXT(m, om_next);
+        assert(m != NULL);
+
+        mb_bytes = m->om_omp->omp_databuf_len;
+        copylen = min(mb_bytes, rem_bytes);
+        copylen &= 0xFFFC;
+        rem_bytes -= copylen;
+        mb_bytes -= copylen;
+        m->om_len = copylen;
+        dst = (uint32_t *)m->om_data;
+        while (copylen > 0) {
+            *dst = *src;
+            ++dst;
+            ++src;
+            copylen -= 4;
+        }
+    }
+
+    /* Copy ble header */
+    ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
+    memcpy(ble_hdr, &g_ble_phy_data.rxhdr, sizeof(struct ble_mbuf_hdr));
+}
+
+void
+ble_phy_isr(void)
+{
+    int rc;
+    uint8_t transition;
+    uint32_t irq_en;
+    struct ble_mbuf_hdr *ble_hdr;
+
+    /* Check for disabled event. This only happens for transmits now */
+    irq_en = ble_xcvr_get_irq_status();
+    if (irq_en & BLE_XCVR_IRQ_F_TX_END) {
+
+        /* Better be in TX state! */
+        assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX);
+        ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_TX_END);
+
+        transition = g_ble_phy_data.phy_transition;
+        if (transition == BLE_PHY_TRANSITION_TX_RX) {
+            /* Disable the phy */
+            /* XXX: count no bufs? */
+            ble_phy_disable();
+        } else {
+            /* Better not be going from rx to tx! */
+            assert(transition == BLE_PHY_TRANSITION_NONE);
+        }
+    }
+
+    /* We get this if we have started to receive a frame */
+    if (irq_en & BLE_XCVR_IRQ_F_RX_START) {
+
+        ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_RX_START);
+
+        /* Call Link Layer receive start function */
+        rc = ble_ll_rx_start(g_ble_phy_data.rxdptr, g_ble_phy_data.phy_chan,
+                             &g_ble_phy_data.rxhdr);
+        if (rc >= 0) {
+            /* XXX: set rx end enable isr */
+        } else {
+            /* Disable PHY */
+            ble_phy_disable();
+            irq_en = 0;
+            ++g_ble_phy_stats.rx_aborts;
+        }
+
+        /* Count rx starts */
+        ++g_ble_phy_stats.rx_starts;
+    }
+
+    /* Receive packet end (we dont enable this for transmit) */
+    if (irq_en & BLE_XCVR_IRQ_F_RX_END) {
+
+        ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_RX_END);
+
+        /* Construct BLE header before handing up */
+        ble_hdr = &g_ble_phy_data.rxhdr;
+        ble_hdr->rxinfo.flags = 0;
+        ble_hdr->rxinfo.rssi = -77;    /* XXX: dummy rssi */
+        ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
+        ble_hdr->rxinfo.phy = BLE_PHY_1M;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+        ble_hdr->rxinfo.aux_data = NULL;
+#endif
+
+        /* Count PHY valid packets */
+        ++g_ble_phy_stats.rx_valid;
+        ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK;
+
+        /* Call Link Layer receive payload function */
+        rc = ble_ll_rx_end(g_ble_phy_data.rxdptr, ble_hdr);
+        if (rc < 0) {
+            /* Disable the PHY. */
+            ble_phy_disable();
+        }
+    }
+
+    /* Count # of interrupts */
+    ++g_ble_phy_stats.phy_isrs;
+}
+
+/**
+ * ble phy init
+ *
+ * Initialize the PHY. This is expected to be called once.
+ *
+ * @return int 0: success; PHY error code otherwise
+ */
+int
+ble_phy_init(void)
+{
+    /* Set phy channel to an invalid channel so first set channel works */
+    g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+    g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
+
+    /* XXX: emulate ISR? */
+
+    return 0;
+}
+
+int
+ble_phy_rx(void)
+{
+    /* Check radio state */
+    if (ble_phy_state_get() != BLE_PHY_STATE_IDLE) {
+        ble_phy_disable();
+        ++g_ble_phy_stats.radio_state_errs;
+        return BLE_PHY_ERR_RADIO_STATE;
+    }
+
+    g_ble_phy_data.phy_state = BLE_PHY_STATE_RX;
+
+    return 0;
+}
+
+void
+ble_phy_restart_rx(void)
+{
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+/**
+ * Called to enable encryption at the PHY. Note that this state will persist
+ * in the PHY; in other words, if you call this function you have to call
+ * disable so that future PHY transmits/receives will not be encrypted.
+ *
+ * @param pkt_counter
+ * @param iv
+ * @param key
+ * @param is_master
+ */
+void
+ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key,
+                       uint8_t is_master)
+{
+}
+
+void
+ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir)
+{
+}
+
+void
+ble_phy_encrypt_disable(void)
+{
+}
+#endif
+
+void
+ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
+{
+    /* Set transmit end callback and arg */
+    g_ble_phy_data.txend_cb = txend_cb;
+    g_ble_phy_data.txend_arg = arg;
+}
+
+/**
+ * Called to set the start time of a transmission.
+ *
+ * This function is called to set the start time when we are not going from
+ * rx to tx automatically.
+ *
+ * NOTE: care must be taken when calling this function. The channel should
+ * already be set.
+ *
+ * @param cputime
+ * @param rem_usecs
+ *
+ * @return int
+ */
+int
+ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+    return 0;
+}
+
+/**
+ * Called to set the start time of a reception
+ *
+ * This function acts a bit differently than transmit. If we are late getting
+ * here we will still attempt to receive.
+ *
+ * NOTE: care must be taken when calling this function. The channel should
+ * already be set.
+ *
+ * @param cputime
+ * @param rem_usecs
+ *
+ * @return int
+ */
+int
+ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+    return 0;
+}
+
+
+int
+ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
+{
+    int rc;
+
+    /* Better have a pdu! */
+    assert(txpdu != NULL);
+
+    if (ble_phy_state_get() != BLE_PHY_STATE_IDLE) {
+        ble_phy_disable();
+        ++g_ble_phy_stats.radio_state_errs;
+        return BLE_PHY_ERR_RADIO_STATE;
+    }
+
+    /* Select tx address */
+    if (g_ble_phy_data.phy_chan < BLE_PHY_NUM_DATA_CHANS) {
+        /* XXX: fix this */
+        assert(0);
+    } else {
+    }
+
+    /* Set the PHY transition */
+    g_ble_phy_data.phy_transition = end_trans;
+
+    /* Set phy state to transmitting and count packet statistics */
+    g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
+    ++g_ble_phy_stats.tx_good;
+    g_ble_phy_stats.tx_bytes += OS_MBUF_PKTHDR(txpdu)->omp_len +
+        BLE_LL_PDU_HDR_LEN;
+    rc = BLE_ERR_SUCCESS;
+
+    return rc;
+}
+
+/**
+ * ble phy txpwr set
+ *
+ * Set the transmit output power (in dBm).
+ *
+ * NOTE: If the output power specified is within the BLE limits but outside
+ * the chip limits, we "rail" the power level so we dont exceed the min/max
+ * chip values.
+ *
+ * @param dbm Power output in dBm.
+ *
+ * @return int 0: success; anything else is an error
+ */
+int
+ble_phy_txpwr_set(int dbm)
+{
+    /* Check valid range */
+    assert(dbm <= BLE_PHY_MAX_PWR_DBM);
+
+    /* "Rail" power level if outside supported range */
+    if (dbm > BLE_XCVR_TX_PWR_MAX_DBM) {
+        dbm = BLE_XCVR_TX_PWR_MAX_DBM;
+    } else {
+        if (dbm < BLE_XCVR_TX_PWR_MIN_DBM) {
+            dbm = BLE_XCVR_TX_PWR_MIN_DBM;
+        }
+    }
+
+    g_ble_phy_data.phy_txpwr_dbm = dbm;
+
+    return 0;
+}
+
+/**
+ * ble phy txpwr round
+ *
+ * Get the rounded transmit output power (in dBm).
+ *
+ * @param dbm Power output in dBm.
+ *
+ * @return int Rounded power in dBm
+ */
+int ble_phy_txpower_round(int dbm)
+{
+    /* "Rail" power level if outside supported range */
+    if (dbm > BLE_XCVR_TX_PWR_MAX_DBM) {
+        dbm = BLE_XCVR_TX_PWR_MAX_DBM;
+    } else {
+        if (dbm < BLE_XCVR_TX_PWR_MIN_DBM) {
+            dbm = BLE_XCVR_TX_PWR_MIN_DBM;
+        }
+    }
+
+    return dbm;
+}
+
+/**
+ * ble phy txpwr get
+ *
+ * Get the transmit power.
+ *
+ * @return int  The current PHY transmit power, in dBm
+ */
+int
+ble_phy_txpwr_get(void)
+{
+    return g_ble_phy_data.phy_txpwr_dbm;
+}
+
+/**
+ * ble phy setchan
+ *
+ * Sets the logical frequency of the transceiver. The input parameter is the
+ * BLE channel index (0 to 39, inclusive). The NRF52 frequency register
+ * works like this: logical frequency = 2400 + FREQ (MHz).
+ *
+ * Thus, to get a logical frequency of 2402 MHz, you would program the
+ * FREQUENCY register to 2.
+ *
+ * @param chan This is the Data Channel Index or Advertising Channel index
+ *
+ * @return int 0: success; PHY error code otherwise
+ */
+int
+ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
+{
+    assert(chan < BLE_PHY_NUM_CHANS);
+
+    /* Check for valid channel range */
+    if (chan >= BLE_PHY_NUM_CHANS) {
+        return BLE_PHY_ERR_INV_PARAM;
+    }
+
+    g_ble_phy_data.phy_access_address = access_addr;
+
+    g_ble_phy_data.phy_chan = chan;
+
+    return 0;
+}
+
+/**
+ * Disable the PHY. This will do the following:
+ *  -> Turn off all phy interrupts.
+ *  -> Disable internal shortcuts.
+ *  -> Disable the radio.
+ *  -> Sets phy state to idle.
+ */
+void
+ble_phy_disable(void)
+{
+    g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+}
+
+/* Gets the current access address */
+uint32_t ble_phy_access_addr_get(void)
+{
+    return g_ble_phy_data.phy_access_address;
+}
+
+/**
+ * Return the phy state
+ *
+ * @return int The current PHY state.
+ */
+int
+ble_phy_state_get(void)
+{
+    return g_ble_phy_data.phy_state;
+}
+
+/**
+ * Called to see if a reception has started
+ *
+ * @return int
+ */
+int
+ble_phy_rx_started(void)
+{
+    return g_ble_phy_data.phy_rx_started;
+}
+
+/**
+ * Called to return the maximum data pdu payload length supported by the
+ * phy. For this chip, if encryption is enabled, the maximum payload is 27
+ * bytes.
+ *
+ * @return uint8_t Maximum data channel PDU payload size supported
+ */
+uint8_t
+ble_phy_max_data_pdu_pyld(void)
+{
+    return BLE_LL_DATA_PDU_MAX_PYLD;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+void
+ble_phy_resolv_list_enable(void)
+{
+    g_ble_phy_data.phy_privacy = 1;
+}
+
+void
+ble_phy_resolv_list_disable(void)
+{
+    g_ble_phy_data.phy_privacy = 0;
+}
+
+/**
+ * Return the transceiver state
+ *
+ * @return int transceiver state.
+ */
+uint8_t
+ble_phy_xcvr_state_get(void)
+{
+   return g_ble_phy_data.phy_state;
+}
+
+#endif
+
+void
+ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs)
+{
+}
diff --git a/nimble/drivers/nrf51/include/ble/xcvr.h b/nimble/drivers/nrf51/include/ble/xcvr.h
new file mode 100644
index 0000000..848c8cc
--- /dev/null
+++ b/nimble/drivers/nrf51/include/ble/xcvr.h
@@ -0,0 +1,48 @@
+/*
+ * 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_BLE_XCVR_
+#define H_BLE_XCVR_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Transceiver specific defintions */
+/* NOTE: we have to account for the RTC output compare issue */
+#define XCVR_PROC_DELAY_USECS         (230)
+
+#define XCVR_RX_START_DELAY_USECS     (140)
+#define XCVR_TX_START_DELAY_USECS     (140)
+#define XCVR_TX_SCHED_DELAY_USECS     \
+    (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+#define XCVR_RX_SCHED_DELAY_USECS     \
+    (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+
+/*
+ * Define HW whitelist size. This is the total possible whitelist size;
+ * not necessarily the size that will be used (may be smaller)
+ */
+#define BLE_HW_WHITE_LIST_SIZE        (8)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_BLE_XCVR_ */
diff --git a/nimble/drivers/nrf51/pkg.yml b/nimble/drivers/nrf51/pkg.yml
new file mode 100644
index 0000000..6c427b5
--- /dev/null
+++ b/nimble/drivers/nrf51/pkg.yml
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+pkg.name: hw/drivers/nimble/nrf51
+pkg.description: BLE driver for nRF51 systems.
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - ble
+    - bluetooth
+
+pkg.apis: ble_driver
+pkg.deps:
+    - net/nimble
+    - net/nimble/controller
diff --git a/nimble/drivers/nrf51/src/ble_hw.c b/nimble/drivers/nrf51/src/ble_hw.c
new file mode 100644
index 0000000..e9b5040
--- /dev/null
+++ b/nimble/drivers/nrf51/src/ble_hw.c
@@ -0,0 +1,482 @@
+/*
+ * 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 <stdint.h>
+#include <assert.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "ble/xcvr.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "nrf51_bitfields.h"
+#include "controller/ble_hw.h"
+#include "bsp/cmsis_nvic.h"
+
+/* Total number of resolving list elements */
+#define BLE_HW_RESOLV_LIST_SIZE     (16)
+
+/* We use this to keep track of which entries are set to valid addresses */
+static uint8_t g_ble_hw_whitelist_mask;
+
+/* Random number generator isr callback */
+ble_rng_isr_cb_t g_ble_rng_isr_cb;
+
+/* If LL privacy is enabled, allocate memory for AAR */
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+
+/* The NRF51 supports up to 16 IRK entries */
+#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16)
+#define NRF_IRK_LIST_ENTRIES    (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
+#else
+#define NRF_IRK_LIST_ENTRIES    (16)
+#endif
+
+/* NOTE: each entry is 16 bytes long. */
+uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4];
+
+/* Current number of IRK entries */
+uint8_t g_nrf_num_irks;
+
+#endif
+
+/* Returns public device address or -1 if not present */
+int
+ble_hw_get_public_addr(ble_addr_t *addr)
+{
+    int rc;
+    uint32_t addr_high;
+    uint32_t addr_low;
+
+    /* Does FICR have a public address */
+    rc = -1;
+    if ((NRF_FICR->DEVICEADDRTYPE & 1) == 0) {
+        addr_low = NRF_FICR->DEVICEADDR[0];
+        addr_high = NRF_FICR->DEVICEADDR[1];
+        rc = 0;
+    } else {
+        /* See if programmed in UICR. Upper 16 bits must all be zero */
+        addr_high = NRF_UICR->CUSTOMER[1];
+        if (addr_high < 65536) {
+            addr_low = NRF_UICR->CUSTOMER[0];
+            rc = 0;
+        }
+    }
+
+    if (!rc) {
+        /* Copy into device address. We can do this because we know platform */
+        memcpy(addr->val, &addr_low, 4);
+        memcpy(&addr->val[4], &addr_high, 2);
+        addr->type = BLE_ADDR_PUBLIC;
+    }
+
+    return rc;
+}
+
+/* Returns random static address or -1 if not present */
+int
+ble_hw_get_static_addr(ble_addr_t *addr)
+{
+    int rc;
+
+    if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) {
+        memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4);
+        memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2);
+        addr->val[5] |= 0xc0;
+        addr->type = BLE_ADDR_RANDOM;
+        rc = 0;
+    } else {
+        rc = -1;
+    }
+
+    return rc;
+}
+
+/**
+ * Clear the whitelist
+ *
+ * @return int
+ */
+void
+ble_hw_whitelist_clear(void)
+{
+    NRF_RADIO->DACNF = 0;
+    g_ble_hw_whitelist_mask = 0;
+}
+
+/**
+ * Add a device to the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
+{
+    int i;
+    uint32_t mask;
+
+    /* Find first ununsed device address match element */
+    mask = 0x01;
+    for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
+        if ((mask & g_ble_hw_whitelist_mask) == 0) {
+            NRF_RADIO->DAB[i] = get_le32(addr);
+            NRF_RADIO->DAP[i] = get_le16(addr + 4);
+            if (addr_type == BLE_ADDR_RANDOM) {
+                NRF_RADIO->DACNF |= (mask << 8);
+            }
+            g_ble_hw_whitelist_mask |= mask;
+            return BLE_ERR_SUCCESS;
+        }
+        mask <<= 1;
+    }
+
+    return BLE_ERR_MEM_CAPACITY;
+}
+
+/**
+ * Remove a device from the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ */
+void
+ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
+{
+    int i;
+    uint8_t cfg_addr;
+    uint16_t dap;
+    uint16_t txadd;
+    uint32_t dab;
+    uint32_t mask;
+
+    /* Find first ununsed device address match element */
+    dab = get_le32(addr);
+    dap = get_le16(addr + 4);
+    txadd = NRF_RADIO->DACNF >> 8;
+    mask = 0x01;
+    for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
+        if (mask & g_ble_hw_whitelist_mask) {
+            if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) {
+                cfg_addr = txadd & mask;
+                if (addr_type == BLE_ADDR_RANDOM) {
+                    if (cfg_addr != 0) {
+                        break;
+                    }
+                } else {
+                    if (cfg_addr == 0) {
+                        break;
+                    }
+                }
+            }
+        }
+        mask <<= 1;
+    }
+
+    if (i < BLE_HW_WHITE_LIST_SIZE) {
+        g_ble_hw_whitelist_mask &= ~mask;
+        NRF_RADIO->DACNF &= ~mask;
+    }
+}
+
+/**
+ * Returns the size of the whitelist in HW
+ *
+ * @return int Number of devices allowed in whitelist
+ */
+uint8_t
+ble_hw_whitelist_size(void)
+{
+    return BLE_HW_WHITE_LIST_SIZE;
+}
+
+/**
+ * Enable the whitelisted devices
+ */
+void
+ble_hw_whitelist_enable(void)
+{
+    /* Enable the configured device addresses */
+    NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask;
+}
+
+/**
+ * Disables the whitelisted devices
+ */
+void
+ble_hw_whitelist_disable(void)
+{
+    /* Disable all whitelist devices */
+    NRF_RADIO->DACNF &= 0x0000ff00;
+}
+
+/**
+ * Boolean function which returns true ('1') if there is a match on the
+ * whitelist.
+ *
+ * @return int
+ */
+int
+ble_hw_whitelist_match(void)
+{
+    return (int)NRF_RADIO->EVENTS_DEVMATCH;
+}
+
+/* Encrypt data */
+int
+ble_hw_encrypt_block(struct ble_encryption_block *ecb)
+{
+    int rc;
+    uint32_t end;
+    uint32_t err;
+
+    /* Stop ECB */
+    NRF_ECB->TASKS_STOPECB = 1;
+    /* XXX: does task stop clear these counters? Anyway to do this quicker? */
+    NRF_ECB->EVENTS_ENDECB = 0;
+    NRF_ECB->EVENTS_ERRORECB = 0;
+    NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
+
+    /* Start ECB */
+    NRF_ECB->TASKS_STARTECB = 1;
+
+    /* Wait till error or done */
+    rc = 0;
+    while (1) {
+        end = NRF_ECB->EVENTS_ENDECB;
+        err = NRF_ECB->EVENTS_ERRORECB;
+        if (end || err) {
+            if (err) {
+                rc = -1;
+            }
+            break;
+        }
+    }
+
+    return rc;
+}
+
+/**
+ * Random number generator ISR.
+ */
+static void
+ble_rng_isr(void)
+{
+    uint8_t rnum;
+
+    /* No callback? Clear and disable interrupts */
+    if (g_ble_rng_isr_cb == NULL) {
+        NRF_RNG->INTENCLR = 1;
+        NRF_RNG->EVENTS_VALRDY = 0;
+        (void)NRF_RNG->SHORTS;
+        return;
+    }
+
+    /* If there is a value ready grab it */
+    if (NRF_RNG->EVENTS_VALRDY) {
+        NRF_RNG->EVENTS_VALRDY = 0;
+        rnum = (uint8_t)NRF_RNG->VALUE;
+        (*g_ble_rng_isr_cb)(rnum);
+    }
+}
+
+/**
+ * Initialize the random number generator
+ *
+ * @param cb
+ * @param bias
+ *
+ * @return int
+ */
+int
+ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
+{
+    /* Set bias */
+    if (bias) {
+        NRF_RNG->CONFIG = 1;
+    } else {
+        NRF_RNG->CONFIG = 0;
+    }
+
+    /* If we were passed a function pointer we need to enable the interrupt */
+    if (cb != NULL) {
+        NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+        NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
+        NVIC_EnableIRQ(RNG_IRQn);
+        g_ble_rng_isr_cb = cb;
+    }
+
+    return 0;
+}
+
+/**
+ * Start the random number generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_start(void)
+{
+    os_sr_t sr;
+
+    /* No need for interrupt if there is no callback */
+    OS_ENTER_CRITICAL(sr);
+    NRF_RNG->EVENTS_VALRDY = 0;
+    if (g_ble_rng_isr_cb) {
+        NRF_RNG->INTENSET = 1;
+    }
+    NRF_RNG->TASKS_START = 1;
+    OS_EXIT_CRITICAL(sr);
+
+    return 0;
+}
+
+/**
+ * Stop the random generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_stop(void)
+{
+    os_sr_t sr;
+
+    /* No need for interrupt if there is no callback */
+    OS_ENTER_CRITICAL(sr);
+    NRF_RNG->INTENCLR = 1;
+    NRF_RNG->TASKS_STOP = 1;
+    NRF_RNG->EVENTS_VALRDY = 0;
+    OS_EXIT_CRITICAL(sr);
+
+    return 0;
+}
+
+/**
+ * Read the random number generator.
+ *
+ * @return uint8_t
+ */
+uint8_t
+ble_hw_rng_read(void)
+{
+    uint8_t rnum;
+
+    /* Wait for a sample */
+    while (NRF_RNG->EVENTS_VALRDY == 0) {
+    }
+
+    NRF_RNG->EVENTS_VALRDY = 0;
+    rnum = (uint8_t)NRF_RNG->VALUE;
+
+    return rnum;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY))
+/**
+ * Clear the resolving list
+ *
+ * @return int
+ */
+void
+ble_hw_resolv_list_clear(void)
+{
+    g_nrf_num_irks = 0;
+}
+
+/**
+ * Add a device to the hw resolving list
+ *
+ * @param irk   Pointer to IRK to add
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_resolv_list_add(uint8_t *irk)
+{
+    uint32_t *nrf_entry;
+
+    /* Find first ununsed device address match element */
+    if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) {
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
+    /* Copy into irk list */
+    nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks];
+    memcpy(nrf_entry, irk, 16);
+
+    /* Add to total */
+    ++g_nrf_num_irks;
+    return BLE_ERR_SUCCESS;
+}
+
+/**
+ * Remove a device from the hw resolving list
+ *
+ * @param index Index of IRK to remove
+ */
+void
+ble_hw_resolv_list_rmv(int index)
+{
+    uint32_t *irk_entry;
+
+    if (index < g_nrf_num_irks) {
+        --g_nrf_num_irks;
+        irk_entry = &g_nrf_irk_list[index];
+        if (g_nrf_num_irks > index) {
+            memmove(irk_entry, irk_entry + 4, g_nrf_num_irks - index);
+        }
+    }
+}
+
+/**
+ * Returns the size of the resolving list. NOTE: this returns the maximum
+ * allowable entries in the HW. Configuration options may limit this.
+ *
+ * @return int Number of devices allowed in resolving list
+ */
+uint8_t
+ble_hw_resolv_list_size(void)
+{
+    return BLE_HW_RESOLV_LIST_SIZE;
+}
+
+/**
+ * Called to determine if the address received was resolved.
+ *
+ * @return int  Negative values indicate unresolved address; positive values
+ *              indicate index in resolving list of resolved address.
+ */
+int
+ble_hw_resolv_list_match(void)
+{
+    uint32_t index;
+
+    if (NRF_AAR->EVENTS_END) {
+        if (NRF_AAR->EVENTS_RESOLVED) {
+            index = NRF_AAR->STATUS;
+            return (int)index;
+        }
+    }
+
+    return -1;
+}
+#endif
diff --git a/nimble/drivers/nrf51/src/ble_phy.c b/nimble/drivers/nrf51/src/ble_phy.c
new file mode 100644
index 0000000..175c652
--- /dev/null
+++ b/nimble/drivers/nrf51/src/ble_phy.c
@@ -0,0 +1,1494 @@
+/*
+ * 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 <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "ble/xcvr.h"
+#include "bsp/cmsis_nvic.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "controller/ble_phy.h"
+#include "controller/ble_ll.h"
+#include "nrf51_bitfields.h"
+
+/* XXX: 4) Make sure RF is higher priority interrupt than schedule */
+
+/*
+ * XXX: Maximum possible transmit time is 1 msec for a 60ppm crystal
+ * and 16ms for a 30ppm crystal! We need to limit PDU size based on
+ * crystal accuracy. Look at this in the spec.
+ */
+
+/* XXX: private header file? */
+extern uint8_t g_nrf_num_irks;
+extern uint32_t g_nrf_irk_list[];
+
+/* To disable all radio interrupts */
+#define NRF_RADIO_IRQ_MASK_ALL  (0x34FF)
+
+/*
+ * We configure the nrf with a 1 byte S0 field, 8 bit length field, and
+ * zero bit S1 field. The preamble is 8 bits long.
+ */
+#define NRF_LFLEN_BITS          (8)
+#define NRF_S0_LEN              (1)
+
+/* Maximum length of frames */
+#define NRF_MAXLEN              (255)
+#define NRF_BALEN               (3)     /* For base address of 3 bytes */
+
+/* Maximum tx power */
+#define NRF_TX_PWR_MAX_DBM      (4)
+#define NRF_TX_PWR_MIN_DBM      (-40)
+
+/* Max. encrypted payload length */
+#define NRF_MAX_ENCRYPTED_PYLD_LEN  (27)
+#define NRF_ENC_HDR_SIZE            (3)
+#define NRF_ENC_BUF_SIZE            \
+    (NRF_MAX_ENCRYPTED_PYLD_LEN + NRF_ENC_HDR_SIZE + BLE_LL_DATA_MIC_LEN)
+
+/* BLE PHY data structure */
+struct ble_phy_obj
+{
+    uint8_t phy_stats_initialized;
+    int8_t  phy_txpwr_dbm;
+    uint8_t phy_chan;
+    uint8_t phy_state;
+    uint8_t phy_transition;
+    uint8_t phy_rx_started;
+    uint8_t phy_encrypted;
+    uint8_t phy_privacy;
+    uint8_t phy_tx_pyld_len;
+    uint8_t *rxdptr;
+    uint32_t phy_aar_scratch;
+    uint32_t phy_access_address;
+    struct ble_mbuf_hdr rxhdr;
+    void *txend_arg;
+    ble_phy_tx_end_func txend_cb;
+    uint32_t phy_start_cputime;
+};
+struct ble_phy_obj g_ble_phy_data;
+
+/* XXX: if 27 byte packets desired we can make this smaller */
+/* Global transmit/receive buffer */
+static uint32_t g_ble_phy_tx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4];
+static uint32_t g_ble_phy_rx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4];
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+/* Make sure word-aligned for faster copies */
+static uint32_t g_ble_phy_enc_buf[(NRF_ENC_BUF_SIZE + 3) / 4];
+#endif
+
+/* Statistics */
+STATS_SECT_START(ble_phy_stats)
+    STATS_SECT_ENTRY(phy_isrs)
+    STATS_SECT_ENTRY(tx_good)
+    STATS_SECT_ENTRY(tx_fail)
+    STATS_SECT_ENTRY(tx_late)
+    STATS_SECT_ENTRY(tx_bytes)
+    STATS_SECT_ENTRY(rx_starts)
+    STATS_SECT_ENTRY(rx_aborts)
+    STATS_SECT_ENTRY(rx_valid)
+    STATS_SECT_ENTRY(rx_crc_err)
+    STATS_SECT_ENTRY(rx_late)
+    STATS_SECT_ENTRY(radio_state_errs)
+    STATS_SECT_ENTRY(rx_hw_err)
+    STATS_SECT_ENTRY(tx_hw_err)
+STATS_SECT_END
+STATS_SECT_DECL(ble_phy_stats) ble_phy_stats;
+
+STATS_NAME_START(ble_phy_stats)
+    STATS_NAME(ble_phy_stats, phy_isrs)
+    STATS_NAME(ble_phy_stats, tx_good)
+    STATS_NAME(ble_phy_stats, tx_fail)
+    STATS_NAME(ble_phy_stats, tx_late)
+    STATS_NAME(ble_phy_stats, tx_bytes)
+    STATS_NAME(ble_phy_stats, rx_starts)
+    STATS_NAME(ble_phy_stats, rx_aborts)
+    STATS_NAME(ble_phy_stats, rx_valid)
+    STATS_NAME(ble_phy_stats, rx_crc_err)
+    STATS_NAME(ble_phy_stats, rx_late)
+    STATS_NAME(ble_phy_stats, radio_state_errs)
+    STATS_NAME(ble_phy_stats, rx_hw_err)
+    STATS_NAME(ble_phy_stats, tx_hw_err)
+STATS_NAME_END(ble_phy_stats)
+
+/*
+ * NOTE:
+ * Tested the following to see what would happen:
+ *  -> NVIC has radio irq enabled (interrupt # 1, mask 0x2).
+ *  -> Set up nrf to receive. Clear ADDRESS event register.
+ *  -> Enable ADDRESS interrupt on nrf5 by writing to INTENSET.
+ *  -> Enable RX.
+ *  -> Disable interrupts globally using OS_ENTER_CRITICAL().
+ *  -> Wait until a packet is received and the ADDRESS event occurs.
+ *  -> Call ble_phy_disable().
+ *
+ *  At this point I wanted to see the state of the cortex NVIC. The IRQ
+ *  pending bit was TRUE for the radio interrupt (as expected) as we never
+ *  serviced the radio interrupt (interrupts were disabled).
+ *
+ *  What was unexpected was this: without clearing the pending IRQ in the NVIC,
+ *  when radio interrupts were re-enabled (address event bit in INTENSET set to
+ *  1) and the radio ADDRESS event register read 1 (it was never cleared after
+ *  the first address event), the radio did not enter the ISR! I would have
+ *  expected that if the following were true, an interrupt would occur:
+ *      -> NVIC ISER bit set to TRUE
+ *      -> NVIC ISPR bit reads TRUE, meaning interrupt is pending.
+ *      -> Radio peripheral interrupts are enabled for some event (or events).
+ *      -> Corresponding event register(s) in radio peripheral read 1.
+ *
+ *  Not sure what the end result of all this is. We will clear the pending
+ *  bit in the NVIC just to be sure when we disable the PHY.
+ */
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+/* Per nordic, the number of bytes needed for scratch is 16 + MAX_PKT_SIZE. */
+#define NRF_ENC_SCRATCH_WORDS   (((NRF_MAX_ENCRYPTED_PYLD_LEN + 16) + 3) / 4)
+
+uint32_t g_nrf_encrypt_scratchpad[NRF_ENC_SCRATCH_WORDS];
+
+struct nrf_ccm_data
+{
+    uint8_t key[16];
+    uint64_t pkt_counter;
+    uint8_t dir_bit;
+    uint8_t iv[8];
+} __attribute__((packed));
+
+struct nrf_ccm_data g_nrf_ccm_data;
+#endif
+
+/**
+ * Copies the data from the phy receive buffer into a mbuf chain.
+ *
+ * @param dptr Pointer to receive buffer
+ * @param rxpdu Pointer to already allocated mbuf chain
+ *
+ * NOTE: the packet header already has the total mbuf length in it. The
+ * lengths of the individual mbufs are not set prior to calling.
+ *
+ */
+void
+ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
+{
+    uint16_t rem_bytes;
+    uint16_t mb_bytes;
+    uint16_t copylen;
+    uint32_t *dst;
+    uint32_t *src;
+    struct os_mbuf *m;
+    struct ble_mbuf_hdr *ble_hdr;
+    struct os_mbuf_pkthdr *pkthdr;
+
+    /* Better be aligned */
+    assert(((uint32_t)dptr & 3) == 0);
+
+    pkthdr = OS_MBUF_PKTHDR(rxpdu);
+    rem_bytes = pkthdr->omp_len;
+
+    /* Fill in the mbuf pkthdr first. */
+    dst = (uint32_t *)(rxpdu->om_data);
+    src = (uint32_t *)dptr;
+
+    mb_bytes = (rxpdu->om_omp->omp_databuf_len - rxpdu->om_pkthdr_len - 4);
+    copylen = min(mb_bytes, rem_bytes);
+    copylen &= 0xFFFC;
+    rem_bytes -= copylen;
+    mb_bytes -= copylen;
+    rxpdu->om_len = copylen;
+    while (copylen > 0) {
+        *dst = *src;
+        ++dst;
+        ++src;
+        copylen -= 4;
+    }
+
+    /* Copy remaining bytes */
+    m = rxpdu;
+    while (rem_bytes > 0) {
+        /* If there are enough bytes in the mbuf, copy them and leave */
+        if (rem_bytes <= mb_bytes) {
+            memcpy(m->om_data + m->om_len, src, rem_bytes);
+            m->om_len += rem_bytes;
+            break;
+        }
+
+        m = SLIST_NEXT(m, om_next);
+        assert(m != NULL);
+
+        mb_bytes = m->om_omp->omp_databuf_len;
+        copylen = min(mb_bytes, rem_bytes);
+        copylen &= 0xFFFC;
+        rem_bytes -= copylen;
+        mb_bytes -= copylen;
+        m->om_len = copylen;
+        dst = (uint32_t *)m->om_data;
+        while (copylen > 0) {
+            *dst = *src;
+            ++dst;
+            ++src;
+            copylen -= 4;
+        }
+    }
+
+    /* Copy ble header */
+    ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
+    memcpy(ble_hdr, &g_ble_phy_data.rxhdr, sizeof(struct ble_mbuf_hdr));
+}
+
+/**
+ * Called when we want to wait if the radio is in either the rx or tx
+ * disable states. We want to wait until that state is over before doing
+ * anything to the radio
+ */
+static void
+nrf_wait_disabled(void)
+{
+    uint32_t state;
+
+    state = NRF_RADIO->STATE;
+    if (state != RADIO_STATE_STATE_Disabled) {
+        if ((state == RADIO_STATE_STATE_RxDisable) ||
+            (state == RADIO_STATE_STATE_TxDisable)) {
+            /* This will end within a short time (6 usecs). Just poll */
+            while (NRF_RADIO->STATE == state) {
+                /* If this fails, something is really wrong. Should last
+                 * no more than 6 usecs */
+            }
+        }
+    }
+}
+
+/**
+ *
+ *
+ */
+int
+ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+    uint32_t next_cc;
+    uint32_t cur_cc;
+    uint32_t cntr;
+    uint32_t delta;
+
+    /*
+     * XXX: The TXEN time is 140 usecs but there may be additional delays
+     * Need to look at this.
+     */
+
+    /*
+     * With the 32.768 kHz crystal, we may need to adjust the RTC compare
+     * value by 1 tick due to the time it takes for TXEN. The code uses a 5 RTC
+     * tick offset, which is 152.5 usecs. The TXEN time is 140 usecs. This
+     * means that with a remainder of 0, TIMER0 should be set to 12 or 13 (as
+     * TIMER0 counts at 1MHz). A remainder of 19 or more we will need to add
+     * 1 tick. We dont need to add 1 tick per se, but it does give us slightly
+     * more time and thus less of a chance to miss a tick. Another note: we
+     * cant set TIMER0 CC to 0 as the compare wont occur; it must be 1 or more.
+     * This is why we subtract 18 (as opposed to 19) as rem_uses will be >= 1.
+     */
+    if (rem_usecs <= 18) {
+        cputime -= 5;
+        rem_usecs += 12;
+    } else {
+        cputime -= 4;
+        rem_usecs -= 18;
+    }
+
+    /*
+     * Can we set the RTC compare to start TIMER0? We can do it if:
+     *      a) Current compare value is not N+1 or N+2 ticks from current
+     *      counter.
+     *      b) The value we want to set is not at least N+2 from current
+     *      counter.
+     *
+     * NOTE: since the counter can tick 1 while we do these calculations we
+     * need to account for it.
+     */
+    next_cc = cputime & 0xffffff;
+    cur_cc = NRF_RTC0->CC[0];
+    cntr = NRF_RTC0->COUNTER;
+
+    delta = (cur_cc - cntr) & 0xffffff;
+    if ((delta <= 3) && (delta != 0)) {
+        return -1;
+    }
+    delta = (next_cc - cntr) & 0xffffff;
+    if ((delta & 0x800000) || (delta < 3)) {
+        return -1;
+    }
+
+    /* Clear and set TIMER0 to fire off at proper time */
+    NRF_TIMER0->TASKS_CLEAR = 1;
+    NRF_TIMER0->CC[0] = rem_usecs;
+    NRF_TIMER0->EVENTS_COMPARE[0] = 0;
+
+    /* Set RTC compare to start TIMER0 */
+    NRF_RTC0->EVENTS_COMPARE[0] = 0;
+    NRF_RTC0->CC[0] = next_cc;
+    NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
+
+    /* Enable PPI */
+    NRF_PPI->CHENSET = PPI_CHEN_CH31_Msk;
+
+    /* Store the cputime at which we set the RTC */
+    g_ble_phy_data.phy_start_cputime = cputime;
+
+    return 0;
+}
+
+/**
+ * Function is used to set PPI so that we can time out waiting for a reception
+ * to occur. This happens for two reasons: we have sent a packet and we are
+ * waiting for a respons (txrx should be set to ENABLE_TXRX) or we are
+ * starting a connection event and we are a slave and we are waiting for the
+ * master to send us a packet (txrx should be set to ENABLE_RX).
+ *
+ * NOTE: when waiting for a txrx turn-around, wfr_usecs is not used as there
+ * is no additional time to wait; we know when we should receive the address of
+ * the received frame.
+ *
+ * @param txrx Flag denoting if this wfr is a txrx turn-around or not.
+ * @param tx_phy_mode phy mode for last TX (not used on nRF51)
+ * @param wfr_usecs Amount of usecs to wait.
+ */
+void
+ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs)
+{
+    uint32_t end_time;
+
+    if (txrx == BLE_PHY_WFR_ENABLE_TXRX) {
+        /*
+         * Timeout occurs an IFS time plus time it takes to receive address
+         * from the transmit end. We add additional time to make sure the
+         * address event comes before the compare. Note that transmit end
+         * is captured in CC[2]. I just made up the 16 usecs I add here.
+         */
+        end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS +
+            ble_phy_mode_pdu_start_off(BLE_PHY_MODE_1M) + 16;
+    } else {
+        /* CC[0] is set to when RXEN occurs. */
+        end_time = NRF_TIMER0->CC[0] + XCVR_RX_START_DELAY_USECS + wfr_usecs +
+            ble_phy_mode_pdu_start_off(BLE_PHY_MODE_1M) + BLE_LL_JITTER_USECS;
+    }
+
+    /* wfr_secs is the time from rxen until timeout */
+    NRF_TIMER0->CC[3] = end_time;
+    NRF_TIMER0->EVENTS_COMPARE[3] = 0;
+
+    /* Enable wait for response PPI */
+    NRF_PPI->CHENSET = (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk);
+
+    /* Enable the disabled interrupt so we time out on events compare */
+    NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
+}
+
+/**
+ * Setup transceiver for receive.
+ */
+static void
+ble_phy_rx_xcvr_setup(void)
+{
+    uint8_t *dptr;
+
+    dptr = (uint8_t *)&g_ble_phy_rx_buf[0];
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+    if (g_ble_phy_data.phy_encrypted) {
+        dptr += 3;
+        NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_enc_buf[0];
+        NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0];
+        NRF_CCM->OUTPTR = (uint32_t)dptr;
+        NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0];
+        NRF_CCM->MODE = CCM_MODE_MODE_Decryption;
+        NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data;
+        NRF_CCM->SHORTS = 0;
+        NRF_CCM->EVENTS_ERROR = 0;
+        NRF_CCM->EVENTS_ENDCRYPT = 0;
+        NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk | PPI_CHEN_CH25_Msk;
+    } else {
+        NRF_RADIO->PACKETPTR = (uint32_t)dptr;
+    }
+#else
+    NRF_RADIO->PACKETPTR = (uint32_t)dptr;
+#endif
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
+    if (g_ble_phy_data.phy_privacy) {
+        dptr += 3;
+        NRF_RADIO->PACKETPTR = (uint32_t)dptr;
+        NRF_RADIO->PCNF0 = (6 << RADIO_PCNF0_LFLEN_Pos) |
+                           (2 << RADIO_PCNF0_S1LEN_Pos) |
+                           (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos);
+        NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Enabled;
+        NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0];
+        NRF_AAR->SCRATCHPTR = (uint32_t)&g_ble_phy_data.phy_aar_scratch;
+        NRF_AAR->EVENTS_END = 0;
+        NRF_AAR->EVENTS_RESOLVED = 0;
+        NRF_AAR->EVENTS_NOTRESOLVED = 0;
+    } else {
+        if (g_ble_phy_data.phy_encrypted == 0) {
+            NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) |
+                               (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos);
+            /* XXX: do I only need to do this once? Figure out what I can do
+               once. */
+            NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled;
+        }
+    }
+#endif
+
+    /* Turn off trigger TXEN on output compare match and AAR on bcmatch */
+    NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk;
+
+    /* Reset the rx started flag. Used for the wait for response */
+    g_ble_phy_data.phy_rx_started = 0;
+    g_ble_phy_data.phy_state = BLE_PHY_STATE_RX;
+    g_ble_phy_data.rxdptr = dptr;
+
+    /* I want to know when 1st byte received (after address) */
+    NRF_RADIO->BCC = 8; /* in bits */
+    NRF_RADIO->EVENTS_ADDRESS = 0;
+    NRF_RADIO->EVENTS_DEVMATCH = 0;
+    NRF_RADIO->EVENTS_BCMATCH = 0;
+    NRF_RADIO->EVENTS_RSSIEND = 0;
+    NRF_RADIO->SHORTS = RADIO_SHORTS_END_DISABLE_Msk |
+                        RADIO_SHORTS_READY_START_Msk |
+                        RADIO_SHORTS_DISABLED_TXEN_Msk |
+                        RADIO_SHORTS_ADDRESS_BCSTART_Msk |
+                        RADIO_SHORTS_ADDRESS_RSSISTART_Msk |
+                        RADIO_SHORTS_DISABLED_RSSISTOP_Msk;
+
+    NRF_RADIO->INTENSET = RADIO_INTENSET_ADDRESS_Msk;
+}
+
+/**
+ * Called from interrupt context when the transmit ends
+ *
+ */
+static void
+ble_phy_tx_end_isr(void)
+{
+    uint8_t was_encrypted;
+    uint8_t transition;
+    uint8_t txlen;
+    uint32_t wfr_time;
+
+    /* If this transmission was encrypted we need to remember it */
+    was_encrypted = g_ble_phy_data.phy_encrypted;
+
+    /* Better be in TX state! */
+    assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX);
+
+    /* Log the event */
+    ble_ll_log(BLE_LL_LOG_ID_PHY_TXEND, g_ble_phy_data.phy_tx_pyld_len,
+               was_encrypted, NRF_TIMER0->CC[2]);
+
+    /* Clear events and clear interrupt on disabled event */
+    NRF_RADIO->EVENTS_DISABLED = 0;
+    NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk;
+    NRF_RADIO->EVENTS_END = 0;
+    wfr_time = NRF_RADIO->SHORTS;
+    (void)wfr_time;
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+    /*
+     * XXX: not sure what to do. We had a HW error during transmission.
+     * For now I just count a stat but continue on like all is good.
+     */
+    if (was_encrypted) {
+        if (NRF_CCM->EVENTS_ERROR) {
+            STATS_INC(ble_phy_stats, tx_hw_err);
+            NRF_CCM->EVENTS_ERROR = 0;
+        }
+    }
+#endif
+
+    /* Call transmit end callback */
+    if (g_ble_phy_data.txend_cb) {
+        g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg);
+    }
+
+    transition = g_ble_phy_data.phy_transition;
+    if (transition == BLE_PHY_TRANSITION_TX_RX) {
+        /* Packet pointer needs to be reset. */
+        ble_phy_rx_xcvr_setup();
+
+        /*
+         * Enable the wait for response timer. Note that cc #1 on
+         * timer 0 contains the transmit start time
+         */
+        txlen = g_ble_phy_data.phy_tx_pyld_len;
+        if (txlen && was_encrypted) {
+            txlen += BLE_LL_DATA_MIC_LEN;
+        }
+        ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, 0, 0);
+    } else {
+        /*
+         * XXX: not sure we need to stop the timer here all the time. Or that
+         * it should be stopped here.
+         */
+        NRF_TIMER0->TASKS_STOP = 1;
+        NRF_TIMER0->TASKS_SHUTDOWN = 1;
+        NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk |
+                           PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk;
+        assert(transition == BLE_PHY_TRANSITION_NONE);
+    }
+}
+
+static void
+ble_phy_rx_end_isr(void)
+{
+    int rc;
+    uint8_t *dptr;
+    uint8_t crcok;
+    struct ble_mbuf_hdr *ble_hdr;
+
+    /* Clear events and clear interrupt */
+    NRF_RADIO->EVENTS_END = 0;
+    NRF_RADIO->INTENCLR = RADIO_INTENCLR_END_Msk;
+
+    /* Disable automatic RXEN */
+    NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
+
+    /* Set RSSI and CRC status flag in header */
+    ble_hdr = &g_ble_phy_data.rxhdr;
+    assert(NRF_RADIO->EVENTS_RSSIEND != 0);
+    ble_hdr->rxinfo.rssi = -1 * NRF_RADIO->RSSISAMPLE;
+
+    dptr = g_ble_phy_data.rxdptr;
+
+    /* Count PHY crc errors and valid packets */
+    crcok = (uint8_t)NRF_RADIO->CRCSTATUS;
+    if (!crcok) {
+        STATS_INC(ble_phy_stats, rx_crc_err);
+    } else {
+        STATS_INC(ble_phy_stats, rx_valid);
+        ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+        if (g_ble_phy_data.phy_encrypted) {
+            /* Only set MIC failure flag if frame is not zero length */
+            if ((dptr[1] != 0) && (NRF_CCM->MICSTATUS == 0)) {
+                ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE;
+            }
+
+            /*
+             * XXX: not sure how to deal with this. This should not
+             * be a MIC failure but we should not hand it up. I guess
+             * this is just some form of rx error and that is how we
+             * handle it? For now, just set CRC error flags
+             */
+            if (NRF_CCM->EVENTS_ERROR) {
+                STATS_INC(ble_phy_stats, rx_hw_err);
+                ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK;
+            }
+
+            /*
+             * XXX: This is a total hack work-around for now but I dont
+             * know what else to do. If ENDCRYPT is not set and we are
+             * encrypted we need to not trust this frame and drop it.
+             */
+            if (NRF_CCM->EVENTS_ENDCRYPT == 0) {
+                STATS_INC(ble_phy_stats, rx_hw_err);
+                ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK;
+            }
+        }
+#endif
+    }
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
+    if (g_ble_phy_data.phy_encrypted || g_ble_phy_data.phy_privacy) {
+        /*
+         * XXX: This is a horrible ugly hack to deal with the RAM S1 byte.
+         * This should get fixed as we should not be handing up the header
+         * and length as part of the pdu.
+         */
+        dptr[2] = dptr[1];
+        dptr[1] = dptr[0];
+        ++dptr;
+    }
+#endif
+    rc = ble_ll_rx_end(dptr, ble_hdr);
+    if (rc < 0) {
+        ble_phy_disable();
+    }
+}
+
+static void
+ble_phy_rx_start_isr(void)
+{
+    int rc;
+    uint32_t state;
+    uint32_t usecs;
+    uint32_t ticks;
+    struct ble_mbuf_hdr *ble_hdr;
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+    uint8_t *dptr;
+
+    dptr = (uint8_t *)&g_ble_phy_rx_buf[0];
+#endif
+
+    /* Clear events and clear interrupt */
+    NRF_RADIO->EVENTS_ADDRESS = 0;
+
+    /* Clear wfr timer channels and DISABLED interrupt */
+    NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk | RADIO_INTENCLR_ADDRESS_Msk;
+    NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk;
+
+    /* Initialize flags, channel and state in ble header at rx start */
+    ble_hdr = &g_ble_phy_data.rxhdr;
+    ble_hdr->rxinfo.flags = ble_ll_state_get();
+    ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
+    ble_hdr->rxinfo.handle = 0;
+    ble_hdr->rxinfo.phy = BLE_PHY_1M;
+    ble_hdr->rxinfo.phy_mode = BLE_PHY_MODE_1M;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    ble_hdr->rxinfo.user_data = NULL;
+#endif
+
+    /*
+     * Calculate receive start time.
+     *
+     * XXX: possibly use other routine with remainder!
+     */
+    usecs = NRF_TIMER0->CC[1] - ble_phy_mode_pdu_start_off(BLE_PHY_MODE_1M);
+    ticks = os_cputime_usecs_to_ticks(usecs);
+    ble_hdr->rem_usecs = usecs - os_cputime_ticks_to_usecs(ticks);
+    if (ble_hdr->rem_usecs == 31) {
+        ble_hdr->rem_usecs = 0;
+        ++ticks;
+    }
+    ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime + ticks;
+
+    /* Wait to get 1st byte of frame */
+    while (1) {
+        state = NRF_RADIO->STATE;
+        if (NRF_RADIO->EVENTS_BCMATCH != 0) {
+            break;
+        }
+
+        /*
+         * If state is disabled, we should have the BCMATCH. If not,
+         * something is wrong!
+         */
+        if (state == RADIO_STATE_STATE_Disabled) {
+            NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+            NRF_RADIO->SHORTS = 0;
+            return;
+        }
+    }
+
+    /* Call Link Layer receive start function */
+    rc = ble_ll_rx_start(g_ble_phy_data.rxdptr, g_ble_phy_data.phy_chan,
+                         &g_ble_phy_data.rxhdr);
+    if (rc >= 0) {
+        /* Set rx started flag and enable rx end ISR */
+        g_ble_phy_data.phy_rx_started = 1;
+        NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk;
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+        /* Must start aar if we need to  */
+        if (g_ble_phy_data.phy_privacy) {
+            NRF_RADIO->EVENTS_BCMATCH = 0;
+            NRF_PPI->CHENSET = PPI_CHEN_CH23_Msk;
+            /*
+             * Setup AAR to resolve AdvA and trigger it after complete address
+             * is received, i.e. after PDU header and AdvA is received.
+             *
+             * AdvA starts at 4th octet in receive buffer, after S0, len and S1
+             * fields.
+             *
+             * In case of extended advertising AdvA is located after extended
+             * header (+2 octets).
+             */
+            if (BLE_MBUF_HDR_EXT_ADV(&g_ble_phy_data.rxhdr)) {
+                NRF_AAR->ADDRPTR = (uint32_t)(dptr + 5);
+                NRF_RADIO->BCC = (BLE_DEV_ADDR_LEN + BLE_LL_PDU_HDR_LEN + 2) * 8;
+
+            } else {
+                NRF_AAR->ADDRPTR = (uint32_t)(dptr + 3);
+                NRF_RADIO->BCC = (BLE_DEV_ADDR_LEN + BLE_LL_PDU_HDR_LEN) * 8;
+            }
+        }
+#endif
+    } else {
+        /* Disable PHY */
+        ble_phy_disable();
+        STATS_INC(ble_phy_stats, rx_aborts);
+    }
+
+    /* Count rx starts */
+    STATS_INC(ble_phy_stats, rx_starts);
+}
+
+static void
+ble_phy_isr(void)
+{
+    uint32_t irq_en;
+
+    /* Read irq register to determine which interrupts are enabled */
+    irq_en = NRF_RADIO->INTENCLR;
+
+    /*
+     * NOTE: order of checking is important! Possible, if things get delayed,
+     * we have both an ADDRESS and DISABLED interrupt in rx state. If we get
+     * an address, we disable the DISABLED interrupt.
+     */
+
+    /* We get this if we have started to receive a frame */
+    if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO->EVENTS_ADDRESS) {
+        irq_en &= ~RADIO_INTENCLR_DISABLED_Msk;
+        ble_phy_rx_start_isr();
+    }
+
+    /* Check for disabled event. This only happens for transmits now */
+    if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) {
+        if (g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) {
+            NRF_RADIO->EVENTS_DISABLED = 0;
+            ble_ll_wfr_timer_exp(NULL);
+        } else {
+            ble_phy_tx_end_isr();
+        }
+    }
+
+    /* Receive packet end (we dont enable this for transmit) */
+    if ((irq_en & RADIO_INTENCLR_END_Msk) && NRF_RADIO->EVENTS_END) {
+        ble_phy_rx_end_isr();
+    }
+
+    /* Ensures IRQ is cleared */
+    irq_en = NRF_RADIO->SHORTS;
+
+    /* Count # of interrupts */
+    STATS_INC(ble_phy_stats, phy_isrs);
+}
+
+/**
+ * ble phy init
+ *
+ * Initialize the PHY.
+ *
+ * @return int 0: success; PHY error code otherwise
+ */
+int
+ble_phy_init(void)
+{
+    int rc;
+
+#if !defined(BLE_XCVR_RFCLK)
+    uint32_t os_tmo;
+
+    /* Make sure HFXO is started */
+    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
+    NRF_CLOCK->TASKS_HFCLKSTART = 1;
+    os_tmo = os_time_get() + (5 * (1000 / OS_TICKS_PER_SEC));
+    while (1) {
+        if (NRF_CLOCK->EVENTS_HFCLKSTARTED) {
+            break;
+        }
+        if ((int32_t)(os_time_get() - os_tmo) > 0) {
+            return BLE_PHY_ERR_INIT;
+        }
+    }
+#endif
+
+    /* Set phy channel to an invalid channel so first set channel works */
+    g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
+
+    /* Toggle peripheral power to reset (just in case) */
+    NRF_RADIO->POWER = 0;
+    NRF_RADIO->POWER = 1;
+
+    /* Disable all interrupts */
+    NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+
+    /* Set configuration registers */
+    NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit;
+    NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) |
+                       (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos);
+    /* XXX: should maxlen be 251 for encryption? */
+    NRF_RADIO->PCNF1 = NRF_MAXLEN |
+                       (RADIO_PCNF1_ENDIAN_Little <<  RADIO_PCNF1_ENDIAN_Pos) |
+                       (NRF_BALEN << RADIO_PCNF1_BALEN_Pos) |
+                       RADIO_PCNF1_WHITEEN_Msk;
+
+    /* Set base0 with the advertising access address */
+    NRF_RADIO->BASE0 = (BLE_ACCESS_ADDR_ADV << 8) & 0xFFFFFF00;
+    NRF_RADIO->PREFIX0 = (BLE_ACCESS_ADDR_ADV >> 24) & 0xFF;
+
+    /* Configure the CRC registers */
+    NRF_RADIO->CRCCNF = RADIO_CRCCNF_SKIPADDR_Msk | RADIO_CRCCNF_LEN_Three;
+
+    /* Configure BLE poly */
+    NRF_RADIO->CRCPOLY = 0x0100065B;
+
+    /* Configure IFS */
+    NRF_RADIO->TIFS = BLE_LL_IFS;
+
+    /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */
+    NRF_PPI->CHENSET = PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk;
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+    NRF_CCM->INTENCLR = 0xffffffff;
+    NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk;
+    NRF_CCM->EVENTS_ERROR = 0;
+    memset(g_nrf_encrypt_scratchpad, 0, sizeof(g_nrf_encrypt_scratchpad));
+#endif
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+    g_ble_phy_data.phy_aar_scratch = 0;
+    NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0];
+    NRF_AAR->INTENCLR = 0xffffffff;
+    NRF_AAR->EVENTS_END = 0;
+    NRF_AAR->EVENTS_RESOLVED = 0;
+    NRF_AAR->EVENTS_NOTRESOLVED = 0;
+    NRF_AAR->NIRK = 0;
+#endif
+
+    /* TIMER0 setup for PHY when using RTC */
+    NRF_TIMER0->TASKS_STOP = 1;
+    NRF_TIMER0->TASKS_SHUTDOWN = 1;
+    NRF_TIMER0->BITMODE = 3;    /* 32-bit timer */
+    NRF_TIMER0->MODE = 0;       /* Timer mode */
+    NRF_TIMER0->PRESCALER = 4;  /* gives us 1 MHz */
+
+    /*
+     * PPI setup.
+     * Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used
+     *            to cancel the wait for response timer.
+     * Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait
+     *            for response timer.
+     */
+    NRF_PPI->CH[4].EEP = (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS);
+    NRF_PPI->CH[4].TEP = (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3]);
+    NRF_PPI->CH[5].EEP = (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]);
+    NRF_PPI->CH[5].TEP = (uint32_t)&(NRF_RADIO->TASKS_DISABLE);
+
+    /* Set isr in vector table and enable interrupt */
+    NVIC_SetPriority(RADIO_IRQn, 0);
+    NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr);
+    NVIC_EnableIRQ(RADIO_IRQn);
+
+    /* Register phy statistics */
+    if (!g_ble_phy_data.phy_stats_initialized) {
+        rc = stats_init_and_reg(STATS_HDR(ble_phy_stats),
+                                STATS_SIZE_INIT_PARMS(ble_phy_stats,
+                                                      STATS_SIZE_32),
+                                STATS_NAME_INIT_PARMS(ble_phy_stats),
+                                "ble_phy");
+        assert(rc == 0);
+
+        g_ble_phy_data.phy_stats_initialized  = 1;
+    }
+
+    return 0;
+}
+
+/**
+ * Puts the phy into receive mode.
+ *
+ * @return int 0: success; BLE Phy error code otherwise
+ */
+int
+ble_phy_rx(void)
+{
+    /* Check radio state */
+    nrf_wait_disabled();
+    if (NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) {
+        ble_phy_disable();
+        STATS_INC(ble_phy_stats, radio_state_errs);
+        return BLE_PHY_ERR_RADIO_STATE;
+    }
+
+    /* Make sure all interrupts are disabled */
+    NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+
+    /* Clear events prior to enabling receive */
+    NRF_RADIO->EVENTS_END = 0;
+    NRF_RADIO->EVENTS_DISABLED = 0;
+
+    /* Setup for rx */
+    ble_phy_rx_xcvr_setup();
+
+    /* Start the receive task in the radio if not automatically going to rx */
+    if ((NRF_PPI->CHEN & PPI_CHEN_CH21_Msk) == 0) {
+        NRF_RADIO->TASKS_RXEN = 1;
+    }
+
+    ble_ll_log(BLE_LL_LOG_ID_PHY_RX, g_ble_phy_data.phy_encrypted, 0, 0);
+
+    return 0;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+/**
+ * Called to enable encryption at the PHY. Note that this state will persist
+ * in the PHY; in other words, if you call this function you have to call
+ * disable so that future PHY transmits/receives will not be encrypted.
+ *
+ * @param pkt_counter
+ * @param iv
+ * @param key
+ * @param is_master
+ */
+void
+ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key,
+                       uint8_t is_master)
+{
+    memcpy(g_nrf_ccm_data.key, key, 16);
+    g_nrf_ccm_data.pkt_counter = pkt_counter;
+    memcpy(g_nrf_ccm_data.iv, iv, 8);
+    g_nrf_ccm_data.dir_bit = is_master;
+    g_ble_phy_data.phy_encrypted = 1;
+
+    /* Encryption uses LFLEN=5, S1LEN = 3. */
+    NRF_RADIO->PCNF0 = (5 << RADIO_PCNF0_LFLEN_Pos) |
+                       (3 << RADIO_PCNF0_S1LEN_Pos) |
+                       (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos);
+
+    /* Enable the module (AAR cannot be on while CCM on) */
+    NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled;
+    NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled;
+}
+
+void
+ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir)
+{
+    g_nrf_ccm_data.pkt_counter = pkt_counter;
+    g_nrf_ccm_data.dir_bit = dir;
+}
+
+void
+ble_phy_encrypt_disable(void)
+{
+    NRF_PPI->CHENCLR = (PPI_CHEN_CH24_Msk | PPI_CHEN_CH25_Msk);
+    NRF_CCM->TASKS_STOP = 1;
+    NRF_CCM->EVENTS_ERROR = 0;
+    NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled;
+
+    /* Switch back to normal length */
+    NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) |
+                       (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos);
+
+    g_ble_phy_data.phy_encrypted = 0;
+}
+#endif
+
+void
+ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
+{
+    /* Set transmit end callback and arg */
+    g_ble_phy_data.txend_cb = txend_cb;
+    g_ble_phy_data.txend_arg = arg;
+}
+
+/**
+ * Called to set the start time of a transmission.
+ *
+ * This function is called to set the start time when we are not going from
+ * rx to tx automatically.
+ *
+ * NOTE: care must be taken when calling this function. The channel should
+ * already be set.
+ *
+ * @param cputime   This is the tick at which the 1st bit of the preamble
+ *                  should be transmitted
+ * @param rem_usecs This is used only when the underlying timing uses a 32.768
+ *                  kHz crystal. It is the # of usecs from the cputime tick
+ *                  at which the first bit of the preamble should be
+ *                  transmitted.
+ * @return int
+ */
+int
+ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+    int rc;
+
+    /* XXX: This should not be necessary, but paranoia is good! */
+    /* Clear timer0 compare to RXEN since we are transmitting */
+    NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
+
+    /*
+     * XXX: The TXEN time is 140 usecs but there may be additional delays
+     * Need to look at this.
+     */
+    if (ble_phy_set_start_time(cputime, rem_usecs) != 0) {
+        STATS_INC(ble_phy_stats, tx_late);
+        ble_phy_disable();
+        rc = BLE_PHY_ERR_TX_LATE;
+    } else {
+        /* Enable PPI to automatically start TXEN */
+        NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk;
+        rc = 0;
+    }
+    return rc;
+}
+/**
+ * Called to set the start time of a reception
+ *
+ * This function acts a bit differently than transmit. If we are late getting
+ * here we will still attempt to receive.
+ *
+ * NOTE: care must be taken when calling this function. The channel should
+ * already be set.
+ *
+ * @param cputime
+ *
+ * @return int
+ */
+int
+ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+    int rc;
+
+    /* XXX: This should not be necessary, but paranoia is good! */
+    /* Clear timer0 compare to TXEN since we are transmitting */
+    NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
+
+    /*
+     * XXX: The RXEN time is 138 usecs but there may be additional delays
+     * Need to look at this.
+     */
+    if (ble_phy_set_start_time(cputime, rem_usecs) != 0) {
+        STATS_INC(ble_phy_stats, rx_late);
+        NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
+        NRF_RADIO->TASKS_RXEN = 1;
+        rc = BLE_PHY_ERR_RX_LATE;
+    } else {
+        /* Enable PPI to automatically start RXEN */
+        NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk;
+
+        /* Start rx */
+        rc = ble_phy_rx();
+    }
+    return rc;
+}
+
+int
+ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
+{
+    int rc;
+    uint8_t *dptr;
+    uint8_t payload_len;
+    uint32_t state;
+    uint32_t shortcuts;
+    struct ble_mbuf_hdr *ble_hdr;
+
+    /* Better have a pdu! */
+    assert(txpdu != NULL);
+
+    /*
+     * This check is to make sure that the radio is not in a state where
+     * it is moving to disabled state. If so, let it get there.
+     */
+    nrf_wait_disabled();
+
+    ble_hdr = BLE_MBUF_HDR_PTR(txpdu);
+    payload_len = ble_hdr->txinfo.pyld_len;
+
+    /*
+     * XXX: Although we may not have to do this here, I clear all the PPI
+     * that should not be used when transmitting. Some of them are only enabled
+     * if encryption and/or privacy is on, but I dont care. Better to be
+     * paranoid, and if you are going to clear one, might as well clear them
+     * all.
+     */
+    NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH23_Msk |
+                       PPI_CHEN_CH25_Msk;
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+    if (g_ble_phy_data.phy_encrypted) {
+        /* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */
+        dptr = (uint8_t *)&g_ble_phy_enc_buf[0];
+        dptr[0] = ble_hdr->txinfo.hdr_byte;
+        dptr[1] = payload_len;
+        dptr[2] = 0;
+        dptr += 3;
+
+        NRF_CCM->SHORTS = 1;
+        NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0];
+        NRF_CCM->OUTPTR = (uint32_t)&g_ble_phy_tx_buf[0];
+        NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0];
+        NRF_CCM->EVENTS_ERROR = 0;
+        NRF_CCM->MODE = CCM_MODE_MODE_Encryption;
+        NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data;
+        NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk;
+    } else {
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+        /* Reconfigure PCNF0 */
+        NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) |
+                           (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos);
+        NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0];
+#endif
+        /* RAM representation has S0 and LENGTH fields (2 bytes) */
+        dptr = (uint8_t *)&g_ble_phy_tx_buf[0];
+        dptr[0] = ble_hdr->txinfo.hdr_byte;
+        dptr[1] = payload_len;
+        dptr += 2;
+    }
+#else
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+    /* Reconfigure PCNF0 */
+    NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) |
+                       (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos);
+#endif
+
+    /* RAM representation has S0 and LENGTH fields (2 bytes) */
+    dptr = (uint8_t *)&g_ble_phy_tx_buf[0];
+    dptr[0] = ble_hdr->txinfo.hdr_byte;
+    dptr[1] = payload_len;
+    dptr += 2;
+#endif
+
+    NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_tx_buf[0];
+
+    /* Clear the ready, end and disabled events */
+    NRF_RADIO->EVENTS_READY = 0;
+    NRF_RADIO->EVENTS_END = 0;
+    NRF_RADIO->EVENTS_DISABLED = 0;
+
+    /* Enable shortcuts for transmit start/end. */
+    shortcuts = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk;
+    if (end_trans == BLE_PHY_TRANSITION_TX_RX) {
+        shortcuts |= RADIO_SHORTS_DISABLED_RXEN_Msk;
+    }
+    NRF_RADIO->SHORTS = shortcuts;
+    NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
+
+    /* Set transmitted payload length */
+    g_ble_phy_data.phy_tx_pyld_len = payload_len;
+
+    /* Set the PHY transition */
+    g_ble_phy_data.phy_transition = end_trans;
+
+    /* If we already started transmitting, abort it! */
+    state = NRF_RADIO->STATE;
+    if (state != RADIO_STATE_STATE_Tx) {
+        /* Copy data from mbuf into transmit buffer */
+        os_mbuf_copydata(txpdu, ble_hdr->txinfo.offset, payload_len, dptr);
+
+        /* Set phy state to transmitting and count packet statistics */
+        g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
+        STATS_INC(ble_phy_stats, tx_good);
+        STATS_INCN(ble_phy_stats, tx_bytes, payload_len + BLE_LL_PDU_HDR_LEN);
+        rc = BLE_ERR_SUCCESS;
+    } else {
+        ble_phy_disable();
+        STATS_INC(ble_phy_stats, tx_late);
+        rc = BLE_PHY_ERR_RADIO_STATE;
+    }
+
+    return rc;
+}
+
+/**
+ * ble phy txpwr set
+ *
+ * Set the transmit output power (in dBm).
+ *
+ * NOTE: If the output power specified is within the BLE limits but outside
+ * the chip limits, we "rail" the power level so we dont exceed the min/max
+ * chip values.
+ *
+ * @param dbm Power output in dBm.
+ *
+ * @return int 0: success; anything else is an error
+ */
+int
+ble_phy_txpwr_set(int dbm)
+{
+    /* Check valid range */
+    assert(dbm <= BLE_PHY_MAX_PWR_DBM);
+
+    /* "Rail" power level if outside supported range */
+    if (dbm > NRF_TX_PWR_MAX_DBM) {
+        dbm = NRF_TX_PWR_MAX_DBM;
+    } else {
+        if (dbm < NRF_TX_PWR_MIN_DBM) {
+            dbm = NRF_TX_PWR_MIN_DBM;
+        }
+    }
+
+    NRF_RADIO->TXPOWER = dbm;
+    g_ble_phy_data.phy_txpwr_dbm = dbm;
+
+    return 0;
+}
+
+/**
+ * ble phy txpwr round
+ *
+ * Get the rounded transmit output power (in dBm).
+ *
+ * @param dbm Power output in dBm.
+ *
+ * @return int Rounded power in dBm
+ */
+int ble_phy_txpower_round(int dbm)
+{
+    /* "Rail" power level if outside supported range */
+    if (dbm > NRF_TX_PWR_MAX_DBM) {
+        dbm = NRF_TX_PWR_MAX_DBM;
+    } else {
+        if (dbm < NRF_TX_PWR_MIN_DBM) {
+            dbm = NRF_TX_PWR_MIN_DBM;
+        }
+    }
+
+    return dbm;
+}
+
+/**
+ * ble phy txpwr get
+ *
+ * Get the transmit power.
+ *
+ * @return int  The current PHY transmit power, in dBm
+ */
+int
+ble_phy_txpwr_get(void)
+{
+    return g_ble_phy_data.phy_txpwr_dbm;
+}
+
+/**
+ * ble phy setchan
+ *
+ * Sets the logical frequency of the transceiver. The input parameter is the
+ * BLE channel index (0 to 39, inclusive). The NRF frequency register works like
+ * this: logical frequency = 2400 + FREQ (MHz).
+ *
+ * Thus, to get a logical frequency of 2402 MHz, you would program the
+ * FREQUENCY register to 2.
+ *
+ * @param chan This is the Data Channel Index or Advertising Channel index
+ *
+ * @return int 0: success; PHY error code otherwise
+ */
+int
+ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
+{
+    uint8_t freq;
+    uint32_t prefix;
+
+    assert(chan < BLE_PHY_NUM_CHANS);
+
+    /* Check for valid channel range */
+    if (chan >= BLE_PHY_NUM_CHANS) {
+        return BLE_PHY_ERR_INV_PARAM;
+    }
+
+    /* Get correct frequency */
+    if (chan < BLE_PHY_NUM_DATA_CHANS) {
+        if (chan < 11) {
+            /* Data channel 0 starts at 2404. 0 - 10 are contiguous */
+            freq = (BLE_PHY_DATA_CHAN0_FREQ_MHZ - 2400) +
+                   (BLE_PHY_CHAN_SPACING_MHZ * chan);
+        } else {
+            /* Data channel 11 starts at 2428. 0 - 10 are contiguous */
+            freq = (BLE_PHY_DATA_CHAN0_FREQ_MHZ - 2400) +
+                   (BLE_PHY_CHAN_SPACING_MHZ * (chan + 1));
+        }
+
+        /* Set current access address */
+        g_ble_phy_data.phy_access_address = access_addr;
+
+        /* Configure logical address 1 and crcinit */
+        prefix = NRF_RADIO->PREFIX0;
+        prefix &= 0xffff00ff;
+        prefix |= ((access_addr >> 24) & 0xFF) << 8;
+        NRF_RADIO->BASE1 = (access_addr << 8) & 0xFFFFFF00;
+        NRF_RADIO->PREFIX0 = prefix;
+        NRF_RADIO->TXADDRESS = 1;
+        NRF_RADIO->RXADDRESSES = (1 << 1);
+        NRF_RADIO->CRCINIT = crcinit;
+    } else {
+        if (chan == 37) {
+            freq = BLE_PHY_CHAN_SPACING_MHZ;
+        } else if (chan == 38) {
+            /* This advertising channel is at 2426 MHz */
+            freq = BLE_PHY_CHAN_SPACING_MHZ * 13;
+        } else {
+            /* This advertising channel is at 2480 MHz */
+            freq = BLE_PHY_CHAN_SPACING_MHZ * 40;
+        }
+
+        /* Logical adddress 0 preconfigured */
+        NRF_RADIO->TXADDRESS = 0;
+        NRF_RADIO->RXADDRESSES = (1 << 0);
+        NRF_RADIO->CRCINIT = BLE_LL_CRCINIT_ADV;
+
+        /* Set current access address */
+        g_ble_phy_data.phy_access_address = BLE_ACCESS_ADDR_ADV;
+    }
+
+    /* Set the frequency and the data whitening initial value */
+    g_ble_phy_data.phy_chan = chan;
+    NRF_RADIO->FREQUENCY = freq;
+    NRF_RADIO->DATAWHITEIV = chan;
+
+    ble_ll_log(BLE_LL_LOG_ID_PHY_SETCHAN, chan, freq, access_addr);
+
+    return 0;
+}
+
+/**
+ * Stop the timer used to count microseconds when using RTC for cputime
+ */
+void
+ble_phy_stop_usec_timer(void)
+{
+    NRF_TIMER0->TASKS_STOP = 1;
+    NRF_TIMER0->TASKS_SHUTDOWN = 1;
+    NRF_RTC0->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk;
+}
+
+/**
+ * ble phy disable irq and ppi
+ *
+ * This routine is to be called when reception was stopped due to either a
+ * wait for response timeout or a packet being received and the phy is to be
+ * restarted in receive mode. Generally, the disable routine is called to stop
+ * the phy.
+ */
+void
+ble_phy_disable_irq_and_ppi(void)
+{
+    NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+    NRF_RADIO->SHORTS = 0;
+    NRF_RADIO->TASKS_DISABLE = 1;
+    NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH20_Msk |
+          PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk | PPI_CHEN_CH24_Msk |
+          PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk;
+    NVIC_ClearPendingIRQ(RADIO_IRQn);
+    g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+}
+
+void
+ble_phy_restart_rx(void)
+{
+    ble_phy_disable_irq_and_ppi();
+    ble_phy_rx();
+}
+
+/**
+ * ble phy disable
+ *
+ * Disables the PHY. This should be called when an event is over. It stops
+ * the usec timer (if used), disables interrupts, disables the RADIO, disables
+ * PPI and sets state to idle.
+ */
+void
+ble_phy_disable(void)
+{
+    ble_ll_log(BLE_LL_LOG_ID_PHY_DISABLE, g_ble_phy_data.phy_state, 0, 0);
+    ble_phy_stop_usec_timer();
+    ble_phy_disable_irq_and_ppi();
+}
+
+/* Gets the current access address */
+uint32_t ble_phy_access_addr_get(void)
+{
+    return g_ble_phy_data.phy_access_address;
+}
+
+/**
+ * Return the phy state
+ *
+ * @return int The current PHY state.
+ */
+int
+ble_phy_state_get(void)
+{
+    return g_ble_phy_data.phy_state;
+}
+
+/**
+ * Called to see if a reception has started
+ *
+ * @return int
+ */
+int
+ble_phy_rx_started(void)
+{
+    return g_ble_phy_data.phy_rx_started;
+}
+
+/**
+ * Return the transceiver state
+ *
+ * @return int transceiver state.
+ */
+uint8_t
+ble_phy_xcvr_state_get(void)
+{
+    uint32_t state;
+    state = NRF_RADIO->STATE;
+    return (uint8_t)state;
+}
+
+/**
+ * Called to return the maximum data pdu payload length supported by the
+ * phy. For this chip, if encryption is enabled, the maximum payload is 27
+ * bytes.
+ *
+ * @return uint8_t Maximum data channel PDU payload size supported
+ */
+uint8_t
+ble_phy_max_data_pdu_pyld(void)
+{
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+    return NRF_MAX_ENCRYPTED_PYLD_LEN;
+#else
+    return BLE_LL_DATA_PDU_MAX_PYLD;
+#endif
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+void
+ble_phy_resolv_list_enable(void)
+{
+    NRF_AAR->NIRK = (uint32_t)g_nrf_num_irks;
+    g_ble_phy_data.phy_privacy = 1;
+}
+
+void
+ble_phy_resolv_list_disable(void)
+{
+    g_ble_phy_data.phy_privacy = 0;
+}
+#endif
+
+#ifdef BLE_XCVR_RFCLK
+void
+ble_phy_rfclk_enable(void)
+{
+    NRF_CLOCK->TASKS_HFCLKSTART = 1;
+}
+
+void
+ble_phy_rfclk_disable(void)
+{
+    NRF_CLOCK->TASKS_HFCLKSTOP = 1;
+}
+#endif
diff --git a/nimble/drivers/nrf52/include/ble/xcvr.h b/nimble/drivers/nrf52/include/ble/xcvr.h
new file mode 100644
index 0000000..757bb80
--- /dev/null
+++ b/nimble/drivers/nrf52/include/ble/xcvr.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_BLE_XCVR_
+#define H_BLE_XCVR_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XCVR_RX_RADIO_RAMPUP_USECS  (40)
+#define XCVR_TX_RADIO_RAMPUP_USECS  (40)
+
+/*
+ * NOTE: we have to account for the RTC output compare issue. We want it to be
+ * 5 ticks.
+ */
+#define XCVR_PROC_DELAY_USECS         (153)
+#define XCVR_RX_START_DELAY_USECS     (XCVR_RX_RADIO_RAMPUP_USECS)
+#define XCVR_TX_START_DELAY_USECS     (XCVR_TX_RADIO_RAMPUP_USECS)
+#define XCVR_TX_SCHED_DELAY_USECS     \
+    (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+#define XCVR_RX_SCHED_DELAY_USECS     \
+    (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+
+/*
+ * Define HW whitelist size. This is the total possible whitelist size;
+ * not necessarily the size that will be used (may be smaller)
+ */
+#define BLE_HW_WHITE_LIST_SIZE        (8)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_BLE_XCVR_ */
diff --git a/nimble/drivers/nrf52/pkg.yml b/nimble/drivers/nrf52/pkg.yml
new file mode 100644
index 0000000..f682667
--- /dev/null
+++ b/nimble/drivers/nrf52/pkg.yml
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+pkg.name: hw/drivers/nimble/nrf52
+pkg.description: BLE driver for nRF52 systems.
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - ble
+    - bluetooth
+
+pkg.apis: ble_driver
+pkg.deps:
+    - net/nimble
+    - net/nimble/controller
diff --git a/nimble/drivers/nrf52/src/ble_hw.c b/nimble/drivers/nrf52/src/ble_hw.c
new file mode 100644
index 0000000..e63ba52
--- /dev/null
+++ b/nimble/drivers/nrf52/src/ble_hw.c
@@ -0,0 +1,486 @@
+/*
+ * 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 <stdint.h>
+#include <assert.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "ble/xcvr.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "nrf52_bitfields.h"
+#include "controller/ble_hw.h"
+#include "bsp/cmsis_nvic.h"
+#include "os/os_trace_api.h"
+
+/* Total number of resolving list elements */
+#define BLE_HW_RESOLV_LIST_SIZE     (16)
+
+/* We use this to keep track of which entries are set to valid addresses */
+static uint8_t g_ble_hw_whitelist_mask;
+
+/* Random number generator isr callback */
+ble_rng_isr_cb_t g_ble_rng_isr_cb;
+
+/* If LL privacy is enabled, allocate memory for AAR */
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+
+/* The NRF51 supports up to 16 IRK entries */
+#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16)
+#define NRF_IRK_LIST_ENTRIES    (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
+#else
+#define NRF_IRK_LIST_ENTRIES    (16)
+#endif
+
+/* NOTE: each entry is 16 bytes long. */
+uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4];
+
+/* Current number of IRK entries */
+uint8_t g_nrf_num_irks;
+
+#endif
+
+/* Returns public device address or -1 if not present */
+int
+ble_hw_get_public_addr(ble_addr_t *addr)
+{
+    int rc;
+    uint32_t addr_high;
+    uint32_t addr_low;
+
+    /* Does FICR have a public address */
+    rc = -1;
+    if ((NRF_FICR->DEVICEADDRTYPE & 1) == 0) {
+        addr_low = NRF_FICR->DEVICEADDR[0];
+        addr_high = NRF_FICR->DEVICEADDR[1];
+        rc = 0;
+    } else {
+        /* See if programmed in UICR. Upper 16 bits must all be zero */
+        addr_high = NRF_UICR->CUSTOMER[1];
+        if (addr_high < 65536) {
+            addr_low = NRF_UICR->CUSTOMER[0];
+            rc = 0;
+        }
+    }
+
+    if (!rc) {
+        /* Copy into device address. We can do this because we know platform */
+        memcpy(addr->val, &addr_low, 4);
+        memcpy(&addr->val[4], &addr_high, 2);
+        addr->type = BLE_ADDR_PUBLIC;
+    }
+
+    return rc;
+}
+
+/* Returns random static address or -1 if not present */
+int
+ble_hw_get_static_addr(ble_addr_t *addr)
+{
+    int rc;
+
+    if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) {
+        memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4);
+        memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2);
+        addr->val[5] |= 0xc0;
+        addr->type = BLE_ADDR_RANDOM;
+        rc = 0;
+    } else {
+        rc = -1;
+    }
+
+    return rc;
+}
+
+/**
+ * Clear the whitelist
+ *
+ * @return int
+ */
+void
+ble_hw_whitelist_clear(void)
+{
+    NRF_RADIO->DACNF = 0;
+    g_ble_hw_whitelist_mask = 0;
+}
+
+/**
+ * Add a device to the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
+{
+    int i;
+    uint32_t mask;
+
+    /* Find first ununsed device address match element */
+    mask = 0x01;
+    for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
+        if ((mask & g_ble_hw_whitelist_mask) == 0) {
+            NRF_RADIO->DAB[i] = get_le32(addr);
+            NRF_RADIO->DAP[i] = get_le16(addr + 4);
+            if (addr_type == BLE_ADDR_RANDOM) {
+                NRF_RADIO->DACNF |= (mask << 8);
+            }
+            g_ble_hw_whitelist_mask |= mask;
+            return BLE_ERR_SUCCESS;
+        }
+        mask <<= 1;
+    }
+
+    return BLE_ERR_MEM_CAPACITY;
+}
+
+/**
+ * Remove a device from the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ */
+void
+ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
+{
+    int i;
+    uint8_t cfg_addr;
+    uint16_t dap;
+    uint16_t txadd;
+    uint32_t dab;
+    uint32_t mask;
+
+    /* Find first ununsed device address match element */
+    dab = get_le32(addr);
+    dap = get_le16(addr + 4);
+    txadd = NRF_RADIO->DACNF >> 8;
+    mask = 0x01;
+    for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
+        if (mask & g_ble_hw_whitelist_mask) {
+            if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) {
+                cfg_addr = txadd & mask;
+                if (addr_type == BLE_ADDR_RANDOM) {
+                    if (cfg_addr != 0) {
+                        break;
+                    }
+                } else {
+                    if (cfg_addr == 0) {
+                        break;
+                    }
+                }
+            }
+        }
+        mask <<= 1;
+    }
+
+    if (i < BLE_HW_WHITE_LIST_SIZE) {
+        g_ble_hw_whitelist_mask &= ~mask;
+        NRF_RADIO->DACNF &= ~mask;
+    }
+}
+
+/**
+ * Returns the size of the whitelist in HW
+ *
+ * @return int Number of devices allowed in whitelist
+ */
+uint8_t
+ble_hw_whitelist_size(void)
+{
+    return BLE_HW_WHITE_LIST_SIZE;
+}
+
+/**
+ * Enable the whitelisted devices
+ */
+void
+ble_hw_whitelist_enable(void)
+{
+    /* Enable the configured device addresses */
+    NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask;
+}
+
+/**
+ * Disables the whitelisted devices
+ */
+void
+ble_hw_whitelist_disable(void)
+{
+    /* Disable all whitelist devices */
+    NRF_RADIO->DACNF &= 0x0000ff00;
+}
+
+/**
+ * Boolean function which returns true ('1') if there is a match on the
+ * whitelist.
+ *
+ * @return int
+ */
+int
+ble_hw_whitelist_match(void)
+{
+    return (int)NRF_RADIO->EVENTS_DEVMATCH;
+}
+
+/* Encrypt data */
+int
+ble_hw_encrypt_block(struct ble_encryption_block *ecb)
+{
+    int rc;
+    uint32_t end;
+    uint32_t err;
+
+    /* Stop ECB */
+    NRF_ECB->TASKS_STOPECB = 1;
+    /* XXX: does task stop clear these counters? Anyway to do this quicker? */
+    NRF_ECB->EVENTS_ENDECB = 0;
+    NRF_ECB->EVENTS_ERRORECB = 0;
+    NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
+
+    /* Start ECB */
+    NRF_ECB->TASKS_STARTECB = 1;
+
+    /* Wait till error or done */
+    rc = 0;
+    while (1) {
+        end = NRF_ECB->EVENTS_ENDECB;
+        err = NRF_ECB->EVENTS_ERRORECB;
+        if (end || err) {
+            if (err) {
+                rc = -1;
+            }
+            break;
+        }
+    }
+
+    return rc;
+}
+
+/**
+ * Random number generator ISR.
+ */
+static void
+ble_rng_isr(void)
+{
+    uint8_t rnum;
+
+    os_trace_enter_isr();
+
+    /* No callback? Clear and disable interrupts */
+    if (g_ble_rng_isr_cb == NULL) {
+        NRF_RNG->INTENCLR = 1;
+        NRF_RNG->EVENTS_VALRDY = 0;
+        (void)NRF_RNG->SHORTS;
+        return;
+    }
+
+    /* If there is a value ready grab it */
+    if (NRF_RNG->EVENTS_VALRDY) {
+        NRF_RNG->EVENTS_VALRDY = 0;
+        rnum = (uint8_t)NRF_RNG->VALUE;
+        (*g_ble_rng_isr_cb)(rnum);
+    }
+    os_trace_exit_isr();
+}
+
+/**
+ * Initialize the random number generator
+ *
+ * @param cb
+ * @param bias
+ *
+ * @return int
+ */
+int
+ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
+{
+    /* Set bias */
+    if (bias) {
+        NRF_RNG->CONFIG = 1;
+    } else {
+        NRF_RNG->CONFIG = 0;
+    }
+
+    /* If we were passed a function pointer we need to enable the interrupt */
+    if (cb != NULL) {
+        NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+        NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
+        NVIC_EnableIRQ(RNG_IRQn);
+        g_ble_rng_isr_cb = cb;
+    }
+
+    return 0;
+}
+
+/**
+ * Start the random number generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_start(void)
+{
+    os_sr_t sr;
+
+    /* No need for interrupt if there is no callback */
+    OS_ENTER_CRITICAL(sr);
+    NRF_RNG->EVENTS_VALRDY = 0;
+    if (g_ble_rng_isr_cb) {
+        NRF_RNG->INTENSET = 1;
+    }
+    NRF_RNG->TASKS_START = 1;
+    OS_EXIT_CRITICAL(sr);
+
+    return 0;
+}
+
+/**
+ * Stop the random generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_stop(void)
+{
+    os_sr_t sr;
+
+    /* No need for interrupt if there is no callback */
+    OS_ENTER_CRITICAL(sr);
+    NRF_RNG->INTENCLR = 1;
+    NRF_RNG->TASKS_STOP = 1;
+    NRF_RNG->EVENTS_VALRDY = 0;
+    OS_EXIT_CRITICAL(sr);
+
+    return 0;
+}
+
+/**
+ * Read the random number generator.
+ *
+ * @return uint8_t
+ */
+uint8_t
+ble_hw_rng_read(void)
+{
+    uint8_t rnum;
+
+    /* Wait for a sample */
+    while (NRF_RNG->EVENTS_VALRDY == 0) {
+    }
+
+    NRF_RNG->EVENTS_VALRDY = 0;
+    rnum = (uint8_t)NRF_RNG->VALUE;
+
+    return rnum;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY))
+/**
+ * Clear the resolving list
+ *
+ * @return int
+ */
+void
+ble_hw_resolv_list_clear(void)
+{
+    g_nrf_num_irks = 0;
+}
+
+/**
+ * Add a device to the hw resolving list
+ *
+ * @param irk   Pointer to IRK to add
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_resolv_list_add(uint8_t *irk)
+{
+    uint32_t *nrf_entry;
+
+    /* Find first ununsed device address match element */
+    if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) {
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
+    /* Copy into irk list */
+    nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks];
+    memcpy(nrf_entry, irk, 16);
+
+    /* Add to total */
+    ++g_nrf_num_irks;
+    return BLE_ERR_SUCCESS;
+}
+
+/**
+ * Remove a device from the hw resolving list
+ *
+ * @param index Index of IRK to remove
+ */
+void
+ble_hw_resolv_list_rmv(int index)
+{
+    uint32_t *irk_entry;
+
+    if (index < g_nrf_num_irks) {
+        --g_nrf_num_irks;
+        irk_entry = &g_nrf_irk_list[index];
+        if (g_nrf_num_irks > index) {
+            memmove(irk_entry, irk_entry + 4, g_nrf_num_irks - index);
+        }
+    }
+}
+
+/**
+ * Returns the size of the resolving list. NOTE: this returns the maximum
+ * allowable entries in the HW. Configuration options may limit this.
+ *
+ * @return int Number of devices allowed in resolving list
+ */
+uint8_t
+ble_hw_resolv_list_size(void)
+{
+    return BLE_HW_RESOLV_LIST_SIZE;
+}
+
+/**
+ * Called to determine if the address received was resolved.
+ *
+ * @return int  Negative values indicate unresolved address; positive values
+ *              indicate index in resolving list of resolved address.
+ */
+int
+ble_hw_resolv_list_match(void)
+{
+    uint32_t index;
+
+    if (NRF_AAR->EVENTS_END) {
+        if (NRF_AAR->EVENTS_RESOLVED) {
+            index = NRF_AAR->STATUS;
+            return (int)index;
+        }
+    }
+
+    return -1;
+}
+#endif
diff --git a/nimble/drivers/nrf52/src/ble_phy.c b/nimble/drivers/nrf52/src/ble_phy.c
new file mode 100644
index 0000000..690bbd7
--- /dev/null
+++ b/nimble/drivers/nrf52/src/ble_phy.c
@@ -0,0 +1,1839 @@
+/*
+ * 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 <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "ble/xcvr.h"
+#include "bsp/cmsis_nvic.h"
+#include "hal/hal_gpio.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "controller/ble_phy.h"
+#include "controller/ble_ll.h"
+#include "nrf.h"
+
+/*
+ * NOTE: This code uses a couple of PPI channels so care should be taken when
+ *       using PPI somewhere else.
+ *
+ * Pre-programmed channels: CH20, CH21, CH23, CH25, CH31
+ * Regular channels: CH4, CH5 and optionally CH17, CH18, CH19
+ *  - CH4 = cancel wfr timer on address match
+ *  - CH5 = disable radio on wfr timer expiry
+ *  - CH17 = (optional) gpio debug for radio ramp-up
+ *  - CH18 = (optional) gpio debug for wfr timer RX enabled
+ *  - CH19 = (optional) gpio debug for wfr timer radio disabled
+ *
+ */
+
+/* XXX: 4) Make sure RF is higher priority interrupt than schedule */
+
+/*
+ * XXX: Maximum possible transmit time is 1 msec for a 60ppm crystal
+ * and 16ms for a 30ppm crystal! We need to limit PDU size based on
+ * crystal accuracy. Look at this in the spec.
+ */
+
+/* XXX: private header file? */
+extern uint8_t g_nrf_num_irks;
+extern uint32_t g_nrf_irk_list[];
+
+/* To disable all radio interrupts */
+#define NRF_RADIO_IRQ_MASK_ALL  (0x34FF)
+
+/*
+ * We configure the nrf with a 1 byte S0 field, 8 bit length field, and
+ * zero bit S1 field. The preamble is 8 bits long.
+ */
+#define NRF_LFLEN_BITS          (8)
+#define NRF_S0LEN               (1)
+#define NRF_S1LEN_BITS          (0)
+#define NRF_CILEN_BITS          (2)
+#define NRF_TERMLEN_BITS        (3)
+
+/* Maximum length of frames */
+#define NRF_MAXLEN              (255)
+#define NRF_BALEN               (3)     /* For base address of 3 bytes */
+
+/* Maximum tx power */
+#define NRF_TX_PWR_MAX_DBM      (4)
+#define NRF_TX_PWR_MIN_DBM      (-40)
+
+/* BLE PHY data structure */
+struct ble_phy_obj
+{
+    uint8_t phy_stats_initialized;
+    int8_t  phy_txpwr_dbm;
+    uint8_t phy_chan;
+    uint8_t phy_state;
+    uint8_t phy_transition;
+    uint8_t phy_rx_started;
+    uint8_t phy_encrypted;
+    uint8_t phy_privacy;
+    uint8_t phy_tx_pyld_len;
+    uint8_t phy_txtorx_phy_mode;
+    uint8_t phy_cur_phy_mode;
+    uint8_t phy_bcc_offset;
+    uint16_t phy_mode_pkt_start_off[BLE_PHY_NUM_MODE];
+    uint32_t phy_aar_scratch;
+    uint32_t phy_access_address;
+    uint32_t phy_pcnf0;
+    struct ble_mbuf_hdr rxhdr;
+    void *txend_arg;
+    ble_phy_tx_end_func txend_cb;
+    uint32_t phy_start_cputime;
+};
+struct ble_phy_obj g_ble_phy_data;
+
+/* XXX: if 27 byte packets desired we can make this smaller */
+/* Global transmit/receive buffer */
+static uint32_t g_ble_phy_tx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4];
+static uint32_t g_ble_phy_rx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4];
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+/* Make sure word-aligned for faster copies */
+static uint32_t g_ble_phy_enc_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4];
+#endif
+
+/* Various radio timings */
+/* Radio ramp-up times in usecs (fast mode) */
+#define BLE_PHY_T_TXENFAST      (XCVR_TX_RADIO_RAMPUP_USECS)
+#define BLE_PHY_T_RXENFAST      (XCVR_RX_RADIO_RAMPUP_USECS)
+/* delay between EVENTS_READY and start of tx */
+static const uint8_t g_ble_phy_t_txdelay[BLE_PHY_NUM_MODE] = { 5, 3, 3, 5 };
+/* delay between EVENTS_END and end of txd packet */
+static const uint8_t g_ble_phy_t_txenddelay[BLE_PHY_NUM_MODE] = { 9, 3, 3, 3 };
+/* delay between rxd access address (w/ TERM1 for coded) and EVENTS_ADDRESS */
+static const uint8_t g_ble_phy_t_rxaddrdelay[BLE_PHY_NUM_MODE] = { 17, 7, 3, 17 };
+/* delay between end of rxd packet and EVENTS_END */
+static const uint8_t g_ble_phy_t_rxenddelay[BLE_PHY_NUM_MODE] = { 27, 7, 3, 22 };
+
+/* Statistics */
+STATS_SECT_START(ble_phy_stats)
+    STATS_SECT_ENTRY(phy_isrs)
+    STATS_SECT_ENTRY(tx_good)
+    STATS_SECT_ENTRY(tx_fail)
+    STATS_SECT_ENTRY(tx_late)
+    STATS_SECT_ENTRY(tx_bytes)
+    STATS_SECT_ENTRY(rx_starts)
+    STATS_SECT_ENTRY(rx_aborts)
+    STATS_SECT_ENTRY(rx_valid)
+    STATS_SECT_ENTRY(rx_crc_err)
+    STATS_SECT_ENTRY(rx_late)
+    STATS_SECT_ENTRY(radio_state_errs)
+    STATS_SECT_ENTRY(rx_hw_err)
+    STATS_SECT_ENTRY(tx_hw_err)
+STATS_SECT_END
+STATS_SECT_DECL(ble_phy_stats) ble_phy_stats;
+
+STATS_NAME_START(ble_phy_stats)
+    STATS_NAME(ble_phy_stats, phy_isrs)
+    STATS_NAME(ble_phy_stats, tx_good)
+    STATS_NAME(ble_phy_stats, tx_fail)
+    STATS_NAME(ble_phy_stats, tx_late)
+    STATS_NAME(ble_phy_stats, tx_bytes)
+    STATS_NAME(ble_phy_stats, rx_starts)
+    STATS_NAME(ble_phy_stats, rx_aborts)
+    STATS_NAME(ble_phy_stats, rx_valid)
+    STATS_NAME(ble_phy_stats, rx_crc_err)
+    STATS_NAME(ble_phy_stats, rx_late)
+    STATS_NAME(ble_phy_stats, radio_state_errs)
+    STATS_NAME(ble_phy_stats, rx_hw_err)
+    STATS_NAME(ble_phy_stats, tx_hw_err)
+STATS_NAME_END(ble_phy_stats)
+
+/*
+ * NOTE:
+ * Tested the following to see what would happen:
+ *  -> NVIC has radio irq enabled (interrupt # 1, mask 0x2).
+ *  -> Set up nrf to receive. Clear ADDRESS event register.
+ *  -> Enable ADDRESS interrupt on nrf5 by writing to INTENSET.
+ *  -> Enable RX.
+ *  -> Disable interrupts globally using OS_ENTER_CRITICAL().
+ *  -> Wait until a packet is received and the ADDRESS event occurs.
+ *  -> Call ble_phy_disable().
+ *
+ *  At this point I wanted to see the state of the cortex NVIC. The IRQ
+ *  pending bit was TRUE for the radio interrupt (as expected) as we never
+ *  serviced the radio interrupt (interrupts were disabled).
+ *
+ *  What was unexpected was this: without clearing the pending IRQ in the NVIC,
+ *  when radio interrupts were re-enabled (address event bit in INTENSET set to
+ *  1) and the radio ADDRESS event register read 1 (it was never cleared after
+ *  the first address event), the radio did not enter the ISR! I would have
+ *  expected that if the following were true, an interrupt would occur:
+ *      -> NVIC ISER bit set to TRUE
+ *      -> NVIC ISPR bit reads TRUE, meaning interrupt is pending.
+ *      -> Radio peripheral interrupts are enabled for some event (or events).
+ *      -> Corresponding event register(s) in radio peripheral read 1.
+ *
+ *  Not sure what the end result of all this is. We will clear the pending
+ *  bit in the NVIC just to be sure when we disable the PHY.
+ */
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+
+/*
+ * Per nordic, the number of bytes needed for scratch is 16 + MAX_PKT_SIZE.
+ * However, when I used a smaller size it still overwrote the scratchpad. Until
+ * I figure this out I am just going to allocate 67 words so we have enough
+ * space for 267 bytes of scratch. I used 268 bytes since not sure if this
+ * needs to be aligned and burning a byte is no big deal.
+ */
+//#define NRF_ENC_SCRATCH_WORDS (((MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE) + 16) + 3) / 4)
+#define NRF_ENC_SCRATCH_WORDS   (67)
+
+uint32_t g_nrf_encrypt_scratchpad[NRF_ENC_SCRATCH_WORDS];
+
+struct nrf_ccm_data
+{
+    uint8_t key[16];
+    uint64_t pkt_counter;
+    uint8_t dir_bit;
+    uint8_t iv[8];
+} __attribute__((packed));
+
+struct nrf_ccm_data g_nrf_ccm_data;
+#endif
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+
+/* Packet start offset (in usecs). This is the preamble plus access address.
+ * For LE Coded PHY this also includes CI and TERM1. */
+uint32_t
+ble_phy_mode_pdu_start_off(int phy_mode)
+{
+    return g_ble_phy_data.phy_mode_pkt_start_off[phy_mode];
+}
+
+void
+ble_phy_mode_set(int cur_phy_mode, int txtorx_phy_mode)
+{
+#if MYNEWT_VAL(BSP_NRF52840)
+    /*
+     * nRF52840 Engineering A Errata v1.2
+     * [164] RADIO: Low sensitivity in long range mode
+     */
+    if ((cur_phy_mode == BLE_PHY_MODE_CODED_125KBPS) ||
+                                (cur_phy_mode == BLE_PHY_MODE_CODED_500KBPS)) {
+        *(volatile uint32_t *)0x4000173C |= 0x80000000;
+        *(volatile uint32_t *)0x4000173C = ((*(volatile uint32_t *)0x4000173C &
+                                            0xFFFFFF00) | 0x5C);
+    } else {
+        *(volatile uint32_t *)0x4000173C &= ~0x80000000;
+    }
+#endif
+
+    if (cur_phy_mode == BLE_PHY_MODE_1M) {
+        NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit;
+        NRF_RADIO->PCNF0 = g_ble_phy_data.phy_pcnf0 |
+            (RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos);
+    } else if (cur_phy_mode == BLE_PHY_MODE_2M) {
+        NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_2Mbit;
+        NRF_RADIO->PCNF0 = g_ble_phy_data.phy_pcnf0 |
+            (RADIO_PCNF0_PLEN_16bit << RADIO_PCNF0_PLEN_Pos);
+    } else if (cur_phy_mode == BLE_PHY_MODE_CODED_125KBPS) {
+        NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR125Kbit;
+        NRF_RADIO->PCNF0 = g_ble_phy_data.phy_pcnf0 |
+            (RADIO_PCNF0_PLEN_LongRange << RADIO_PCNF0_PLEN_Pos) |
+            (NRF_CILEN_BITS << RADIO_PCNF0_CILEN_Pos) |
+            (NRF_TERMLEN_BITS << RADIO_PCNF0_TERMLEN_Pos);
+    } else if (cur_phy_mode == BLE_PHY_MODE_CODED_500KBPS) {
+        NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR500Kbit;
+        NRF_RADIO->PCNF0 = g_ble_phy_data.phy_pcnf0 |
+            (RADIO_PCNF0_PLEN_LongRange << RADIO_PCNF0_PLEN_Pos) |
+            (NRF_CILEN_BITS << RADIO_PCNF0_CILEN_Pos) |
+            (NRF_TERMLEN_BITS << RADIO_PCNF0_TERMLEN_Pos);
+    } else {
+        assert(0);
+    }
+
+    g_ble_phy_data.phy_cur_phy_mode = (uint8_t)cur_phy_mode;
+    g_ble_phy_data.phy_txtorx_phy_mode = (uint8_t)txtorx_phy_mode;
+}
+#endif
+
+int
+ble_phy_get_cur_phy(void)
+{
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    switch (g_ble_phy_data.phy_cur_phy_mode) {
+        case BLE_PHY_MODE_1M:
+            return BLE_PHY_1M;
+        case BLE_PHY_MODE_2M:
+            return BLE_PHY_2M;
+        case BLE_PHY_MODE_CODED_125KBPS:
+        case BLE_PHY_MODE_CODED_500KBPS:
+            return BLE_PHY_CODED;
+        default:
+            assert(0);
+            return -1;
+    }
+#else
+    return BLE_PHY_1M;
+#endif
+}
+
+/**
+ * Copies the data from the phy receive buffer into a mbuf chain.
+ *
+ * @param dptr Pointer to receive buffer
+ * @param rxpdu Pointer to already allocated mbuf chain
+ *
+ * NOTE: the packet header already has the total mbuf length in it. The
+ * lengths of the individual mbufs are not set prior to calling.
+ *
+ */
+void
+ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
+{
+    uint16_t rem_bytes;
+    uint16_t mb_bytes;
+    uint16_t copylen;
+    uint32_t *dst;
+    uint32_t *src;
+    struct os_mbuf *m;
+    struct ble_mbuf_hdr *ble_hdr;
+    struct os_mbuf_pkthdr *pkthdr;
+
+    /* Better be aligned */
+    assert(((uint32_t)dptr & 3) == 0);
+
+    pkthdr = OS_MBUF_PKTHDR(rxpdu);
+    rem_bytes = pkthdr->omp_len;
+
+    /* Fill in the mbuf pkthdr first. */
+    dst = (uint32_t *)(rxpdu->om_data);
+    src = (uint32_t *)dptr;
+
+    mb_bytes = (rxpdu->om_omp->omp_databuf_len - rxpdu->om_pkthdr_len - 4);
+    copylen = min(mb_bytes, rem_bytes);
+    copylen &= 0xFFFC;
+    rem_bytes -= copylen;
+    mb_bytes -= copylen;
+    rxpdu->om_len = copylen;
+    while (copylen > 0) {
+        *dst = *src;
+        ++dst;
+        ++src;
+        copylen -= 4;
+    }
+
+    /* Copy remaining bytes */
+    m = rxpdu;
+    while (rem_bytes > 0) {
+        /* If there are enough bytes in the mbuf, copy them and leave */
+        if (rem_bytes <= mb_bytes) {
+            memcpy(m->om_data + m->om_len, src, rem_bytes);
+            m->om_len += rem_bytes;
+            break;
+        }
+
+        m = SLIST_NEXT(m, om_next);
+        assert(m != NULL);
+
+        mb_bytes = m->om_omp->omp_databuf_len;
+        copylen = min(mb_bytes, rem_bytes);
+        copylen &= 0xFFFC;
+        rem_bytes -= copylen;
+        mb_bytes -= copylen;
+        m->om_len = copylen;
+        dst = (uint32_t *)m->om_data;
+        while (copylen > 0) {
+            *dst = *src;
+            ++dst;
+            ++src;
+            copylen -= 4;
+        }
+    }
+
+    /* Copy ble header */
+    ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
+    memcpy(ble_hdr, &g_ble_phy_data.rxhdr, sizeof(struct ble_mbuf_hdr));
+}
+
+/**
+ * Called when we want to wait if the radio is in either the rx or tx
+ * disable states. We want to wait until that state is over before doing
+ * anything to the radio
+ */
+static void
+nrf_wait_disabled(void)
+{
+    uint32_t state;
+
+    state = NRF_RADIO->STATE;
+    if (state != RADIO_STATE_STATE_Disabled) {
+        if ((state == RADIO_STATE_STATE_RxDisable) ||
+            (state == RADIO_STATE_STATE_TxDisable)) {
+            /* This will end within a short time (6 usecs). Just poll */
+            while (NRF_RADIO->STATE == state) {
+                /* If this fails, something is really wrong. Should last
+                 * no more than 6 usecs */
+            }
+        }
+    }
+}
+
+/**
+ *
+ *
+ */
+static int
+ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs, bool tx)
+{
+    uint32_t next_cc;
+    uint32_t cur_cc;
+    uint32_t cntr;
+    uint32_t delta;
+
+    /*
+     * We need to adjust start time to include radio ramp-up and TX pipeline
+     * delay (the latter only if applicable, so only for TX).
+     *
+     * Radio ramp-up time is 40 usecs and TX delay is 3 or 5 usecs depending on
+     * phy, thus we'll offset RTC by 2 full ticks (61 usecs) and then compensate
+     * using TIMER0 with 1 usec precision.
+     */
+
+    cputime -= 2;
+    rem_usecs += 61;
+    if (tx) {
+        rem_usecs -= BLE_PHY_T_TXENFAST;
+        rem_usecs -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode];
+    } else {
+        rem_usecs -= BLE_PHY_T_RXENFAST;
+    }
+
+    /*
+     * rem_usecs will be no more than 2 ticks, but if it is more than single
+     * tick then we should better count one more low-power tick rather than
+     * 30 high-power usecs. Also make sure we don't set TIMER0 CC to 0 as the
+     * compare won't occur.
+     */
+
+    if (rem_usecs > 30) {
+        cputime++;
+        rem_usecs -= 30;
+    }
+
+    /*
+     * Can we set the RTC compare to start TIMER0? We can do it if:
+     *      a) Current compare value is not N+1 or N+2 ticks from current
+     *      counter.
+     *      b) The value we want to set is not at least N+2 from current
+     *      counter.
+     *
+     * NOTE: since the counter can tick 1 while we do these calculations we
+     * need to account for it.
+     */
+    next_cc = cputime & 0xffffff;
+    cur_cc = NRF_RTC0->CC[0];
+    cntr = NRF_RTC0->COUNTER;
+
+    delta = (cur_cc - cntr) & 0xffffff;
+    if ((delta <= 3) && (delta != 0)) {
+        return -1;
+    }
+    delta = (next_cc - cntr) & 0xffffff;
+    if ((delta & 0x800000) || (delta < 3)) {
+        return -1;
+    }
+
+    /* Clear and set TIMER0 to fire off at proper time */
+    NRF_TIMER0->TASKS_CLEAR = 1;
+    NRF_TIMER0->CC[0] = rem_usecs;
+    NRF_TIMER0->EVENTS_COMPARE[0] = 0;
+
+    /* Set RTC compare to start TIMER0 */
+    NRF_RTC0->EVENTS_COMPARE[0] = 0;
+    NRF_RTC0->CC[0] = next_cc;
+    NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
+
+    /* Enable PPI */
+    NRF_PPI->CHENSET = PPI_CHEN_CH31_Msk;
+
+    /* Store the cputime at which we set the RTC */
+    g_ble_phy_data.phy_start_cputime = cputime;
+
+    return 0;
+}
+
+/**
+ * Function is used to set PPI so that we can time out waiting for a reception
+ * to occur. This happens for two reasons: we have sent a packet and we are
+ * waiting for a respons (txrx should be set to ENABLE_TXRX) or we are
+ * starting a connection event and we are a slave and we are waiting for the
+ * master to send us a packet (txrx should be set to ENABLE_RX).
+ *
+ * NOTE: when waiting for a txrx turn-around, wfr_usecs is not used as there
+ * is no additional time to wait; we know when we should receive the address of
+ * the received frame.
+ *
+ * @param txrx Flag denoting if this wfr is a txrx turn-around or not.
+ * @param tx_phy_mode phy mode for last TX (only valid for TX->RX)
+ * @param wfr_usecs Amount of usecs to wait.
+ */
+void
+ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs)
+{
+    uint32_t end_time;
+    uint8_t phy;
+
+    phy = g_ble_phy_data.phy_cur_phy_mode;
+
+    if (txrx == BLE_PHY_WFR_ENABLE_TXRX) {
+        /* RX shall start exactly T_IFS after TX end captured in CC[2] */
+        end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS;
+        /* Adjust for delay between EVENT_END and actual TX end time */
+        end_time += g_ble_phy_t_txenddelay[tx_phy_mode];
+        /* Wait a bit longer due to allowed active clock accuracy */
+        end_time += 2;
+#if MYNEWT_VAL(BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN) > 0
+        if ((phy == BLE_PHY_MODE_CODED_125KBPS) ||
+                                    (phy == BLE_PHY_MODE_CODED_500KBPS)) {
+            /*
+             * Some controllers exceed T_IFS when transmitting on coded phy
+             * so let's wait a bit longer to be able to talk to them if this
+             * workaround is enabled.
+             */
+            end_time += MYNEWT_VAL(BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN);
+        }
+#endif
+    } else {
+        /*
+         * RX shall start no later than wfr_usecs after RX enabled.
+         * CC[0] is the time of RXEN so adjust for radio ram-up.
+         * Do not add jitter since this is already covered by LL.
+         */
+        end_time = NRF_TIMER0->CC[0] + BLE_PHY_T_RXENFAST + wfr_usecs;
+    }
+
+    /*
+     * Note: on LE Coded EVENT_ADDRESS is fired after TERM1 is received, so
+     *       we are actually calculating relative to start of packet payload
+     *       which is fine.
+     */
+
+    /* Adjust for receiving access address since this triggers EVENT_ADDRESS */
+    end_time += ble_phy_mode_pdu_start_off(phy);
+    /* Adjust for delay between actual access address RX and EVENT_ADDRESS */
+    end_time += g_ble_phy_t_rxaddrdelay[phy];
+
+    /* wfr_secs is the time from rxen until timeout */
+    NRF_TIMER0->CC[3] = end_time;
+    NRF_TIMER0->EVENTS_COMPARE[3] = 0;
+
+    /* Enable wait for response PPI */
+    NRF_PPI->CHENSET = (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk);
+
+    /* Enable the disabled interrupt so we time out on events compare */
+    NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
+}
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+static uint32_t
+ble_phy_get_ccm_datarate(void)
+{
+#if BLE_LL_BT5_PHY_SUPPORTED
+    switch (g_ble_phy_data.phy_cur_phy_mode) {
+    case BLE_PHY_MODE_1M:
+        return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos;
+    case BLE_PHY_MODE_2M:
+        return CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos;
+    case BLE_PHY_MODE_CODED_125KBPS:
+        return CCM_MODE_DATARATE_125Kbps << CCM_MODE_DATARATE_Pos;
+    case BLE_PHY_MODE_CODED_500KBPS:
+        return CCM_MODE_DATARATE_500Kbps << CCM_MODE_DATARATE_Pos;
+    }
+
+    assert(0);
+    return 0;
+#else
+    return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos;
+#endif
+}
+#endif
+
+/**
+ * Setup transceiver for receive.
+ */
+static void
+ble_phy_rx_xcvr_setup(void)
+{
+    uint8_t *dptr;
+
+    dptr = (uint8_t *)&g_ble_phy_rx_buf[0];
+    dptr += 3;
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+    if (g_ble_phy_data.phy_encrypted) {
+        NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_enc_buf[0];
+        NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0];
+        NRF_CCM->OUTPTR = (uint32_t)dptr;
+        NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0];
+        NRF_CCM->MODE = CCM_MODE_LENGTH_Msk | CCM_MODE_MODE_Decryption |
+                                                    ble_phy_get_ccm_datarate();
+        NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data;
+        NRF_CCM->SHORTS = 0;
+        NRF_CCM->EVENTS_ERROR = 0;
+        NRF_CCM->EVENTS_ENDCRYPT = 0;
+        NRF_CCM->TASKS_KSGEN = 1;
+        NRF_PPI->CHENSET = PPI_CHEN_CH25_Msk;
+    } else {
+        NRF_RADIO->PACKETPTR = (uint32_t)dptr;
+    }
+#else
+    NRF_RADIO->PACKETPTR = (uint32_t)dptr;
+#endif
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+    if (g_ble_phy_data.phy_privacy) {
+        NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Enabled;
+        NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0];
+        NRF_AAR->SCRATCHPTR = (uint32_t)&g_ble_phy_data.phy_aar_scratch;
+        NRF_AAR->EVENTS_END = 0;
+        NRF_AAR->EVENTS_RESOLVED = 0;
+        NRF_AAR->EVENTS_NOTRESOLVED = 0;
+    } else {
+        if (g_ble_phy_data.phy_encrypted == 0) {
+            NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled;
+        }
+    }
+#endif
+
+    /* Turn off trigger TXEN on output compare match and AAR on bcmatch */
+    NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk;
+
+    /* Reset the rx started flag. Used for the wait for response */
+    g_ble_phy_data.phy_rx_started = 0;
+    g_ble_phy_data.phy_state = BLE_PHY_STATE_RX;
+
+#if BLE_LL_BT5_PHY_SUPPORTED
+    /*
+     * On Coded PHY there are CI and TERM1 fields before PDU starts so we need
+     * to take this into account when setting up BCC.
+     */
+    if (g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_125KBPS ||
+            g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_500KBPS) {
+        g_ble_phy_data.phy_bcc_offset = 5;
+    } else {
+        g_ble_phy_data.phy_bcc_offset = 0;
+    }
+#else
+    g_ble_phy_data.phy_bcc_offset = 0;
+#endif
+
+    /* I want to know when 1st byte received (after address) */
+    NRF_RADIO->BCC = 8 + g_ble_phy_data.phy_bcc_offset; /* in bits */
+    NRF_RADIO->EVENTS_ADDRESS = 0;
+    NRF_RADIO->EVENTS_DEVMATCH = 0;
+    NRF_RADIO->EVENTS_BCMATCH = 0;
+    NRF_RADIO->EVENTS_RSSIEND = 0;
+    NRF_RADIO->EVENTS_CRCOK = 0;
+    NRF_RADIO->SHORTS = RADIO_SHORTS_END_DISABLE_Msk |
+                        RADIO_SHORTS_READY_START_Msk |
+                        RADIO_SHORTS_ADDRESS_BCSTART_Msk |
+                        RADIO_SHORTS_ADDRESS_RSSISTART_Msk |
+                        RADIO_SHORTS_DISABLED_RSSISTOP_Msk;
+
+    NRF_RADIO->INTENSET = RADIO_INTENSET_ADDRESS_Msk;
+}
+
+/**
+ * Called from interrupt context when the transmit ends
+ *
+ */
+static void
+ble_phy_tx_end_isr(void)
+{
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+    int phy;
+#endif
+    uint8_t tx_phy_mode;
+    uint8_t was_encrypted;
+    uint8_t transition;
+    uint32_t rx_time;
+    uint32_t wfr_time;
+
+    /* Store PHY on which we've just transmitted smth */
+    tx_phy_mode = g_ble_phy_data.phy_cur_phy_mode;
+
+    /* If this transmission was encrypted we need to remember it */
+    was_encrypted = g_ble_phy_data.phy_encrypted;
+
+    /* Better be in TX state! */
+    assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX);
+
+    /* Log the event */
+    ble_ll_log(BLE_LL_LOG_ID_PHY_TXEND, g_ble_phy_data.phy_tx_pyld_len,
+               was_encrypted, NRF_TIMER0->CC[2]);
+    (void)was_encrypted;
+
+    /* Clear events and clear interrupt on disabled event */
+    NRF_RADIO->EVENTS_DISABLED = 0;
+    NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk;
+    NRF_RADIO->EVENTS_END = 0;
+    wfr_time = NRF_RADIO->SHORTS;
+    (void)wfr_time;
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+    /*
+     * XXX: not sure what to do. We had a HW error during transmission.
+     * For now I just count a stat but continue on like all is good.
+     */
+    if (was_encrypted) {
+        if (NRF_CCM->EVENTS_ERROR) {
+            STATS_INC(ble_phy_stats, tx_hw_err);
+            NRF_CCM->EVENTS_ERROR = 0;
+        }
+    }
+#endif
+
+    /* Call transmit end callback */
+    if (g_ble_phy_data.txend_cb) {
+        g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg);
+    }
+
+    transition = g_ble_phy_data.phy_transition;
+    if (transition == BLE_PHY_TRANSITION_TX_RX) {
+
+#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
+        /* See if a new phy has been specified for tx to rx transition */
+        phy = g_ble_phy_data.phy_txtorx_phy_mode;
+        if (phy != g_ble_phy_data.phy_cur_phy_mode) {
+            ble_phy_mode_set(phy, phy);
+        }
+#endif
+
+        /* Packet pointer needs to be reset. */
+        ble_phy_rx_xcvr_setup();
+
+        ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, tx_phy_mode, 0);
+
+        /* Schedule RX exactly T_IFS after TX end captured in CC[2] */
+        rx_time = NRF_TIMER0->CC[2] + BLE_LL_IFS;
+        /* Adjust for delay between EVENT_END and actual TX end time */
+        rx_time += g_ble_phy_t_txenddelay[tx_phy_mode];
+        /* Adjust for radio ramp-up */
+        rx_time -= BLE_PHY_T_RXENFAST;
+        /* Start listening a bit earlier due to allowed active clock accuracy */
+        rx_time -= 2;
+
+        NRF_TIMER0->CC[0] = rx_time;
+        NRF_TIMER0->EVENTS_COMPARE[0] = 0;
+        NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk;
+    } else {
+        /*
+         * XXX: not sure we need to stop the timer here all the time. Or that
+         * it should be stopped here.
+         */
+        NRF_TIMER0->TASKS_STOP = 1;
+        NRF_TIMER0->TASKS_SHUTDOWN = 1;
+        NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk |
+                           PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk;
+        assert(transition == BLE_PHY_TRANSITION_NONE);
+    }
+}
+
+static inline uint8_t
+ble_phy_get_cur_rx_phy_mode(void)
+{
+    uint8_t phy;
+
+    phy = g_ble_phy_data.phy_cur_phy_mode;
+
+#if BLE_LL_BT5_PHY_SUPPORTED
+    /*
+     * For Coded PHY mode can be set to either codings since actual coding is
+     * set in packet header. However, here we need actual coding of received
+     * packet as this determines pipeline delays so need to figure this out
+     * using CI field.
+     */
+    if ((phy == BLE_PHY_MODE_CODED_125KBPS) ||
+                                    (phy == BLE_PHY_MODE_CODED_500KBPS)) {
+        /*
+         * XXX CI field value is bits [2:1] in NRF_RADIO->PDUSTAT which is
+         *     available in SDK v14.0 - it's NRF_RADIO->RESERVED7[0] in
+         *     SDK v11.0 so let's use it for now
+         */
+        phy = NRF_RADIO->RESERVED7[0] & 0x06 ?
+                                        BLE_PHY_MODE_CODED_500KBPS :
+                                        BLE_PHY_MODE_CODED_125KBPS;
+    }
+#endif
+
+    return phy;
+}
+
+static void
+ble_phy_rx_end_isr(void)
+{
+    int rc;
+    uint8_t *dptr;
+    uint8_t crcok;
+    uint32_t tx_time;
+    struct ble_mbuf_hdr *ble_hdr;
+
+    /* Clear events and clear interrupt */
+    NRF_RADIO->EVENTS_END = 0;
+    NRF_RADIO->INTENCLR = RADIO_INTENCLR_END_Msk;
+
+    /* Disable automatic RXEN */
+    NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
+
+    /* Set RSSI and CRC status flag in header */
+    ble_hdr = &g_ble_phy_data.rxhdr;
+    assert(NRF_RADIO->EVENTS_RSSIEND != 0);
+    ble_hdr->rxinfo.rssi = -1 * NRF_RADIO->RSSISAMPLE;
+
+    dptr = (uint8_t *)&g_ble_phy_rx_buf[0];
+    dptr += 3;
+
+    /* Count PHY crc errors and valid packets */
+    crcok = NRF_RADIO->EVENTS_CRCOK;
+    if (!crcok) {
+        STATS_INC(ble_phy_stats, rx_crc_err);
+    } else {
+        STATS_INC(ble_phy_stats, rx_valid);
+        ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK;
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+        if (g_ble_phy_data.phy_encrypted) {
+            /* Only set MIC failure flag if frame is not zero length */
+            if ((dptr[1] != 0) && (NRF_CCM->MICSTATUS == 0)) {
+                ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE;
+            }
+
+            /*
+             * XXX: not sure how to deal with this. This should not
+             * be a MIC failure but we should not hand it up. I guess
+             * this is just some form of rx error and that is how we
+             * handle it? For now, just set CRC error flags
+             */
+            if (NRF_CCM->EVENTS_ERROR) {
+                STATS_INC(ble_phy_stats, rx_hw_err);
+                ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK;
+            }
+
+            /*
+             * XXX: This is a total hack work-around for now but I dont
+             * know what else to do. If ENDCRYPT is not set and we are
+             * encrypted we need to not trust this frame and drop it.
+             */
+            if (NRF_CCM->EVENTS_ENDCRYPT == 0) {
+                STATS_INC(ble_phy_stats, rx_hw_err);
+                ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK;
+            }
+        }
+#endif
+    }
+
+    /*
+     * Let's schedule TX now and we will just cancel it after processing RXed
+     * packet if we don't need TX.
+     *
+     * We need this to initiate connection in case AUX_CONNECT_REQ was sent on
+     * LE Coded S8. In this case the time we process RXed packet is roughly the
+     * same as the limit when we need to have TX scheduled (i.e. TIMER0 and PPI
+     * armed) so we may simply miss the slot and set the timer in the past.
+     *
+     * When TX is scheduled in advance, we may event process packet a bit longer
+     * during radio ramp-up - this gives us extra 40 usecs which is more than
+     * enough.
+     */
+
+    /* Schedule TX exactly T_IFS after RX end captured in CC[2] */
+    tx_time = NRF_TIMER0->CC[2] + BLE_LL_IFS;
+    /* Adjust for delay between actual RX end time and EVENT_END */
+    tx_time -= g_ble_phy_t_rxenddelay[ble_hdr->rxinfo.phy_mode];
+    /* Adjust for radio ramp-up */
+    tx_time -= BLE_PHY_T_TXENFAST;
+    /* Adjust for delay between EVENT_READY and actual TX start time */
+    /* XXX: we may have asymmetric phy so next phy may be different... */
+    tx_time -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode];
+
+    NRF_TIMER0->CC[0] = tx_time;
+    NRF_TIMER0->EVENTS_COMPARE[0] = 0;
+    NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk;
+
+    /*
+     * XXX: This is a horrible ugly hack to deal with the RAM S1 byte
+     * that is not sent over the air but is present here. Simply move the
+     * data pointer to deal with it. Fix this later.
+     */
+    dptr[2] = dptr[1];
+    dptr[1] = dptr[0];
+    rc = ble_ll_rx_end(dptr + 1, ble_hdr);
+    if (rc < 0) {
+        ble_phy_disable();
+    }
+}
+
+static bool
+ble_phy_rx_start_isr(void)
+{
+    int rc;
+    uint32_t state;
+    uint32_t usecs;
+    uint32_t pdu_usecs;
+    uint32_t ticks;
+    struct ble_mbuf_hdr *ble_hdr;
+    uint8_t *dptr;
+
+    dptr = (uint8_t *)&g_ble_phy_rx_buf[0];
+
+    /* Clear events and clear interrupt */
+    NRF_RADIO->EVENTS_ADDRESS = 0;
+
+    /* Clear wfr timer channels and DISABLED interrupt */
+    NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk | RADIO_INTENCLR_ADDRESS_Msk;
+    NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk;
+
+    /* Initialize the ble mbuf header */
+    ble_hdr = &g_ble_phy_data.rxhdr;
+    ble_hdr->rxinfo.flags = ble_ll_state_get();
+    ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
+    ble_hdr->rxinfo.handle = 0;
+    ble_hdr->rxinfo.phy = ble_phy_get_cur_phy();
+    ble_hdr->rxinfo.phy_mode = ble_phy_get_cur_rx_phy_mode();
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    ble_hdr->rxinfo.user_data = NULL;
+#endif
+
+    /*
+     * Calculate accurate packets start time (with remainder)
+     *
+     * We may start receiving packet somewhere during preamble in which case
+     * it is possible that actual transmission started before TIMER0 was
+     * running - need to take this into account.
+     */
+    usecs = NRF_TIMER0->CC[1];
+    pdu_usecs = ble_phy_mode_pdu_start_off(ble_hdr->rxinfo.phy_mode) +
+                g_ble_phy_t_rxaddrdelay[ble_hdr->rxinfo.phy_mode];
+    if (usecs < pdu_usecs) {
+        ticks--;
+        usecs += 30;
+    }
+    usecs -= pdu_usecs;
+
+    ticks = os_cputime_usecs_to_ticks(usecs);
+    usecs -= os_cputime_ticks_to_usecs(ticks);
+    if (usecs == 31) {
+        usecs = 0;
+        ++ticks;
+    }
+
+    ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime + ticks;
+    ble_hdr->rem_usecs = usecs;
+
+    /* XXX: I wonder if we always have the 1st byte. If we need to wait for
+     * rx chain delay, it could be 18 usecs from address interrupt. The
+       nrf52 may be able to get here early. */
+    /* Wait to get 1st byte of frame */
+    while (1) {
+        state = NRF_RADIO->STATE;
+        if (NRF_RADIO->EVENTS_BCMATCH != 0) {
+            break;
+        }
+
+        /*
+         * If state is disabled, we should have the BCMATCH. If not,
+         * something is wrong!
+         */
+        if (state == RADIO_STATE_STATE_Disabled) {
+            NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+            NRF_RADIO->SHORTS = 0;
+            return false;
+        }
+    }
+
+    /* Call Link Layer receive start function */
+    rc = ble_ll_rx_start(dptr + 3,
+                         g_ble_phy_data.phy_chan,
+                         &g_ble_phy_data.rxhdr);
+    if (rc >= 0) {
+        /* Set rx started flag and enable rx end ISR */
+        g_ble_phy_data.phy_rx_started = 1;
+        NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk;
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+        /* Must start aar if we need to  */
+        if (g_ble_phy_data.phy_privacy) {
+            NRF_RADIO->EVENTS_BCMATCH = 0;
+            NRF_PPI->CHENSET = PPI_CHEN_CH23_Msk;
+
+            /*
+             * Setup AAR to resolve AdvA and trigger it after complete address
+             * is received, i.e. after PDU header and AdvA is received.
+             *
+             * AdvA starts at 4th octet in receive buffer, after S0, len and S1
+             * fields.
+             *
+             * In case of extended advertising AdvA is located after extended
+             * header (+2 octets).
+             */
+            if (BLE_MBUF_HDR_EXT_ADV(&g_ble_phy_data.rxhdr)) {
+                NRF_AAR->ADDRPTR = (uint32_t)(dptr + 5);
+                NRF_RADIO->BCC = (BLE_DEV_ADDR_LEN + BLE_LL_PDU_HDR_LEN + 2) * 8 +
+                                 g_ble_phy_data.phy_bcc_offset;
+            } else {
+                NRF_AAR->ADDRPTR = (uint32_t)(dptr + 3);
+                NRF_RADIO->BCC = (BLE_DEV_ADDR_LEN + BLE_LL_PDU_HDR_LEN) * 8 +
+                                 g_ble_phy_data.phy_bcc_offset;
+            }
+        }
+#endif
+    } else {
+        /* Disable PHY */
+        ble_phy_disable();
+        STATS_INC(ble_phy_stats, rx_aborts);
+    }
+
+    /* Count rx starts */
+    STATS_INC(ble_phy_stats, rx_starts);
+
+    return true;
+}
+
+static void
+ble_phy_isr(void)
+{
+    uint32_t irq_en;
+
+    /* Read irq register to determine which interrupts are enabled */
+    irq_en = NRF_RADIO->INTENCLR;
+
+    /*
+     * NOTE: order of checking is important! Possible, if things get delayed,
+     * we have both an ADDRESS and DISABLED interrupt in rx state. If we get
+     * an address, we disable the DISABLED interrupt.
+     */
+
+    /* We get this if we have started to receive a frame */
+    if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO->EVENTS_ADDRESS) {
+        /*
+         * wfr timer is calculated to expire at the exact time we should start
+         * receiving a packet (with 1 usec precision) so it is possible  it will
+         * fire at the same time as EVENT_ADDRESS. If this happens, radio will
+         * be disabled while we are waiting for EVENT_BCCMATCH after 1st byte
+         * of payload is received and ble_phy_rx_start_isr() will fail. In this
+         * case we should not clear DISABLED irq mask so it will be handled as
+         * regular radio disabled event below. In other case radio was disabled
+         * on purpose and there's nothing more to handle so we can clear mask.
+         */
+        if (ble_phy_rx_start_isr()) {
+            irq_en &= ~RADIO_INTENCLR_DISABLED_Msk;
+        }
+    }
+
+    /* Check for disabled event. This only happens for transmits now */
+    if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) {
+        if (g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) {
+            NRF_RADIO->EVENTS_DISABLED = 0;
+            ble_ll_wfr_timer_exp(NULL);
+        } else if (g_ble_phy_data.phy_state == BLE_PHY_STATE_IDLE) {
+            assert(0);
+        } else {
+            ble_phy_tx_end_isr();
+        }
+    }
+
+    /* Receive packet end (we dont enable this for transmit) */
+    if ((irq_en & RADIO_INTENCLR_END_Msk) && NRF_RADIO->EVENTS_END) {
+        ble_phy_rx_end_isr();
+    }
+
+    /* Ensures IRQ is cleared */
+    irq_en = NRF_RADIO->SHORTS;
+
+    /* Count # of interrupts */
+    STATS_INC(ble_phy_stats, phy_isrs);
+}
+
+#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 || \
+        MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 || \
+        MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0
+static inline void
+ble_phy_dbg_time_setup_gpiote(int index, int pin)
+{
+    hal_gpio_init_out(pin, 0);
+
+    NRF_GPIOTE->CONFIG[index] =
+                        (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
+                        ((pin & 0x1F) << GPIOTE_CONFIG_PSEL_Pos) |
+                        ((pin > 31) << GPIOTE_CONFIG_PORT_Pos);
+}
+#endif
+
+static void
+ble_phy_dbg_time_setup(void)
+{
+    int gpiote_idx __attribute__((unused)) = 8;
+
+    /*
+     * We setup GPIOTE starting from last configuration index to minimize risk
+     * of conflict with GPIO setup via hal. It's not great solution, but since
+     * this is just debugging code we can live with this.
+     */
+
+#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0
+    ble_phy_dbg_time_setup_gpiote(--gpiote_idx,
+                              MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN));
+
+    NRF_PPI->CH[17].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY);
+    NRF_PPI->CH[17].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]);
+    NRF_PPI->CHENSET = PPI_CHEN_CH17_Msk;
+
+    /* CH[20] and PPI CH[21] are on to trigger TASKS_TXEN or TASKS_RXEN */
+    NRF_PPI->FORK[20].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]);
+    NRF_PPI->FORK[21].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]);
+#endif
+
+#if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0
+    ble_phy_dbg_time_setup_gpiote(--gpiote_idx,
+                              MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN));
+
+    /* CH[26] and CH[27] are always on for EVENT_ADDRESS and EVENT_END */
+    NRF_PPI->FORK[26].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]);
+    NRF_PPI->FORK[27].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]);
+#endif
+
+#if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0
+    ble_phy_dbg_time_setup_gpiote(--gpiote_idx,
+                              MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN));
+
+    NRF_PPI->CH[18].EEP = (uint32_t)&(NRF_RADIO->EVENTS_RXREADY);
+    NRF_PPI->CH[18].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]);
+    NRF_PPI->CH[19].EEP = (uint32_t)&(NRF_RADIO->EVENTS_DISABLED);
+    NRF_PPI->CH[19].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]);
+    NRF_PPI->CHENSET = PPI_CHEN_CH18_Msk | PPI_CHEN_CH19_Msk;
+
+    /* CH[4] and CH[5] are always on for wfr */
+    NRF_PPI->FORK[4].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]);
+    NRF_PPI->FORK[5].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]);
+#endif
+}
+
+/**
+ * ble phy init
+ *
+ * Initialize the PHY.
+ *
+ * @return int 0: success; PHY error code otherwise
+ */
+int
+ble_phy_init(void)
+{
+    int rc;
+
+    /* Set packet start offsets for various phys */
+    g_ble_phy_data.phy_mode_pkt_start_off[BLE_PHY_MODE_1M] = 40;  /* 40 usecs */
+    g_ble_phy_data.phy_mode_pkt_start_off[BLE_PHY_MODE_2M] = 24;  /* 24 usecs */
+    g_ble_phy_data.phy_mode_pkt_start_off[BLE_PHY_MODE_CODED_125KBPS] = 376;  /* 376 usecs */
+    g_ble_phy_data.phy_mode_pkt_start_off[BLE_PHY_MODE_CODED_500KBPS] = 376;  /* 376 usecs */
+
+    /* Default phy to use is 1M */
+    g_ble_phy_data.phy_cur_phy_mode = BLE_PHY_MODE_1M;
+    g_ble_phy_data.phy_txtorx_phy_mode = BLE_PHY_MODE_1M;
+
+#if !defined(BLE_XCVR_RFCLK)
+    uint32_t os_tmo;
+
+    /* Make sure HFXO is started */
+    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
+    NRF_CLOCK->TASKS_HFCLKSTART = 1;
+    os_tmo = os_time_get() + (5 * (1000 / OS_TICKS_PER_SEC));
+    while (1) {
+        if (NRF_CLOCK->EVENTS_HFCLKSTARTED) {
+            break;
+        }
+        if ((int32_t)(os_time_get() - os_tmo) > 0) {
+            return BLE_PHY_ERR_INIT;
+        }
+    }
+#endif
+
+    /* Set phy channel to an invalid channel so first set channel works */
+    g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
+
+    /* Toggle peripheral power to reset (just in case) */
+    NRF_RADIO->POWER = 0;
+    NRF_RADIO->POWER = 1;
+
+    /* Disable all interrupts */
+    NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+
+    /* Set configuration registers */
+    NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit;
+    g_ble_phy_data.phy_pcnf0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos)    |
+                               RADIO_PCNF0_S1INCL_Msk                       |
+                               (NRF_S0LEN << RADIO_PCNF0_S0LEN_Pos)        |
+                               (NRF_S1LEN_BITS << RADIO_PCNF0_S1LEN_Pos);
+    NRF_RADIO->PCNF0 = g_ble_phy_data.phy_pcnf0;
+
+    /* XXX: should maxlen be 251 for encryption? */
+    NRF_RADIO->PCNF1 = NRF_MAXLEN |
+                       (RADIO_PCNF1_ENDIAN_Little <<  RADIO_PCNF1_ENDIAN_Pos) |
+                       (NRF_BALEN << RADIO_PCNF1_BALEN_Pos) |
+                       RADIO_PCNF1_WHITEEN_Msk;
+
+    /* Enable radio fast ramp-up */
+    NRF_RADIO->MODECNF0 |= (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos) &
+                            RADIO_MODECNF0_RU_Msk;
+
+    /* Set logical address 1 for TX and RX */
+    NRF_RADIO->TXADDRESS  = 0;
+    NRF_RADIO->RXADDRESSES  = (1 << 0);
+
+    /* Configure the CRC registers */
+    NRF_RADIO->CRCCNF = (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos) | RADIO_CRCCNF_LEN_Three;
+
+    /* Configure BLE poly */
+    NRF_RADIO->CRCPOLY = 0x0000065B;
+
+    /* Configure IFS */
+    NRF_RADIO->TIFS = BLE_LL_IFS;
+
+    /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */
+    NRF_PPI->CHENSET = PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk;
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+    NRF_CCM->INTENCLR = 0xffffffff;
+    NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk;
+    NRF_CCM->EVENTS_ERROR = 0;
+    memset(g_nrf_encrypt_scratchpad, 0, sizeof(g_nrf_encrypt_scratchpad));
+#endif
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+    g_ble_phy_data.phy_aar_scratch = 0;
+    NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0];
+    NRF_AAR->INTENCLR = 0xffffffff;
+    NRF_AAR->EVENTS_END = 0;
+    NRF_AAR->EVENTS_RESOLVED = 0;
+    NRF_AAR->EVENTS_NOTRESOLVED = 0;
+    NRF_AAR->NIRK = 0;
+#endif
+
+    /* TIMER0 setup for PHY when using RTC */
+    NRF_TIMER0->TASKS_STOP = 1;
+    NRF_TIMER0->TASKS_SHUTDOWN = 1;
+    NRF_TIMER0->BITMODE = 3;    /* 32-bit timer */
+    NRF_TIMER0->MODE = 0;       /* Timer mode */
+    NRF_TIMER0->PRESCALER = 4;  /* gives us 1 MHz */
+
+    /*
+     * PPI setup.
+     * Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used
+     *            to cancel the wait for response timer.
+     * Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait
+     *            for response timer.
+     */
+    NRF_PPI->CH[4].EEP = (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS);
+    NRF_PPI->CH[4].TEP = (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3]);
+    NRF_PPI->CH[5].EEP = (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]);
+    NRF_PPI->CH[5].TEP = (uint32_t)&(NRF_RADIO->TASKS_DISABLE);
+
+    /* Set isr in vector table and enable interrupt */
+    NVIC_SetPriority(RADIO_IRQn, 0);
+    NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr);
+    NVIC_EnableIRQ(RADIO_IRQn);
+
+    /* Register phy statistics */
+    if (!g_ble_phy_data.phy_stats_initialized) {
+        rc = stats_init_and_reg(STATS_HDR(ble_phy_stats),
+                                STATS_SIZE_INIT_PARMS(ble_phy_stats,
+                                                      STATS_SIZE_32),
+                                STATS_NAME_INIT_PARMS(ble_phy_stats),
+                                "ble_phy");
+        assert(rc == 0);
+
+        g_ble_phy_data.phy_stats_initialized  = 1;
+    }
+
+    ble_phy_dbg_time_setup();
+
+    return 0;
+}
+
+/**
+ * Puts the phy into receive mode.
+ *
+ * @return int 0: success; BLE Phy error code otherwise
+ */
+int
+ble_phy_rx(void)
+{
+    /* Check radio state */
+    nrf_wait_disabled();
+    if (NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) {
+        ble_phy_disable();
+        STATS_INC(ble_phy_stats, radio_state_errs);
+        return BLE_PHY_ERR_RADIO_STATE;
+    }
+
+    /* Make sure all interrupts are disabled */
+    NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+
+    /* Clear events prior to enabling receive */
+    NRF_RADIO->EVENTS_END = 0;
+    NRF_RADIO->EVENTS_DISABLED = 0;
+
+    /* Setup for rx */
+    ble_phy_rx_xcvr_setup();
+
+    /* Start the receive task in the radio if not automatically going to rx */
+    if ((NRF_PPI->CHEN & PPI_CHEN_CH21_Msk) == 0) {
+        NRF_RADIO->TASKS_RXEN = 1;
+    }
+
+    ble_ll_log(BLE_LL_LOG_ID_PHY_RX, g_ble_phy_data.phy_encrypted, 0, 0);
+
+    return 0;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+/**
+ * Called to enable encryption at the PHY. Note that this state will persist
+ * in the PHY; in other words, if you call this function you have to call
+ * disable so that future PHY transmits/receives will not be encrypted.
+ *
+ * @param pkt_counter
+ * @param iv
+ * @param key
+ * @param is_master
+ */
+void
+ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key,
+                       uint8_t is_master)
+{
+    memcpy(g_nrf_ccm_data.key, key, 16);
+    g_nrf_ccm_data.pkt_counter = pkt_counter;
+    memcpy(g_nrf_ccm_data.iv, iv, 8);
+    g_nrf_ccm_data.dir_bit = is_master;
+    g_ble_phy_data.phy_encrypted = 1;
+    /* Enable the module (AAR cannot be on while CCM on) */
+    NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled;
+    NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled;
+}
+
+void
+ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir)
+{
+    g_nrf_ccm_data.pkt_counter = pkt_counter;
+    g_nrf_ccm_data.dir_bit = dir;
+}
+
+void
+ble_phy_encrypt_disable(void)
+{
+    NRF_PPI->CHENCLR = PPI_CHEN_CH25_Msk;
+    NRF_CCM->TASKS_STOP = 1;
+    NRF_CCM->EVENTS_ERROR = 0;
+    NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled;
+
+    g_ble_phy_data.phy_encrypted = 0;
+}
+#endif
+
+void
+ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
+{
+    /* Set transmit end callback and arg */
+    g_ble_phy_data.txend_cb = txend_cb;
+    g_ble_phy_data.txend_arg = arg;
+}
+
+/**
+ * Called to set the start time of a transmission.
+ *
+ * This function is called to set the start time when we are not going from
+ * rx to tx automatically.
+ *
+ * NOTE: care must be taken when calling this function. The channel should
+ * already be set.
+ *
+ * @param cputime   This is the tick at which the 1st bit of the preamble
+ *                  should be transmitted
+ * @param rem_usecs This is used only when the underlying timing uses a 32.768
+ *                  kHz crystal. It is the # of usecs from the cputime tick
+ *                  at which the first bit of the preamble should be
+ *                  transmitted.
+ * @return int
+ */
+int
+ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+    int rc;
+
+    /* XXX: This should not be necessary, but paranoia is good! */
+    /* Clear timer0 compare to RXEN since we are transmitting */
+    NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
+
+    if (ble_phy_set_start_time(cputime, rem_usecs, true) != 0) {
+        STATS_INC(ble_phy_stats, tx_late);
+        ble_phy_disable();
+        rc = BLE_PHY_ERR_TX_LATE;
+    } else {
+        /* Enable PPI to automatically start TXEN */
+        NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk;
+        rc = 0;
+    }
+    return rc;
+}
+
+/**
+ * Called to set the start time of a reception
+ *
+ * This function acts a bit differently than transmit. If we are late getting
+ * here we will still attempt to receive.
+ *
+ * NOTE: care must be taken when calling this function. The channel should
+ * already be set.
+ *
+ * @param cputime
+ *
+ * @return int
+ */
+int
+ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+    int rc = 0;
+
+    /* XXX: This should not be necessary, but paranoia is good! */
+    /* Clear timer0 compare to TXEN since we are transmitting */
+    NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
+
+    if (ble_phy_set_start_time(cputime, rem_usecs, false) != 0) {
+        STATS_INC(ble_phy_stats, rx_late);
+        NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
+        NRF_RADIO->TASKS_RXEN = 1;
+        rc = BLE_PHY_ERR_RX_LATE;
+    } else {
+        /* Enable PPI to automatically start RXEN */
+        NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk;
+
+        /* Start rx */
+        rc = ble_phy_rx();
+    }
+    return rc;
+}
+
+int
+ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
+{
+    int rc;
+    uint8_t *dptr;
+    uint8_t *pktptr;
+    uint8_t payload_len;
+    uint32_t state;
+    uint32_t shortcuts;
+    struct ble_mbuf_hdr *ble_hdr;
+
+    /* Better have a pdu! */
+    assert(txpdu != NULL);
+
+    /*
+     * This check is to make sure that the radio is not in a state where
+     * it is moving to disabled state. If so, let it get there.
+     */
+    nrf_wait_disabled();
+
+    ble_hdr = BLE_MBUF_HDR_PTR(txpdu);
+    payload_len = ble_hdr->txinfo.pyld_len;
+
+    /*
+     * XXX: Although we may not have to do this here, I clear all the PPI
+     * that should not be used when transmitting. Some of them are only enabled
+     * if encryption and/or privacy is on, but I dont care. Better to be
+     * paranoid, and if you are going to clear one, might as well clear them
+     * all.
+     */
+    NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH23_Msk |
+                       PPI_CHEN_CH25_Msk;
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+    if (g_ble_phy_data.phy_encrypted) {
+        dptr = (uint8_t *)&g_ble_phy_enc_buf[0];
+        ++dptr;
+        pktptr = (uint8_t *)&g_ble_phy_tx_buf[0];
+        NRF_CCM->SHORTS = 1;
+        NRF_CCM->INPTR = (uint32_t)dptr;
+        NRF_CCM->OUTPTR = (uint32_t)pktptr;
+        NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0];
+        NRF_CCM->EVENTS_ERROR = 0;
+        NRF_CCM->MODE = CCM_MODE_LENGTH_Msk | ble_phy_get_ccm_datarate();
+        NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data;
+        NRF_CCM->TASKS_KSGEN = 1;
+    } else {
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+        NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0];
+#endif
+        dptr = (uint8_t *)&g_ble_phy_tx_buf[0];
+        ++dptr;
+        pktptr = dptr;
+    }
+#else
+    dptr = (uint8_t *)&g_ble_phy_tx_buf[0];
+    ++dptr;
+    pktptr = dptr;
+#endif
+
+    /* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */
+    dptr[0] = ble_hdr->txinfo.hdr_byte;
+    dptr[1] = payload_len;
+    dptr[2] = 0;
+    dptr += 3;
+    NRF_RADIO->PACKETPTR = (uint32_t)pktptr;
+
+    /* Clear the ready, end and disabled events */
+    NRF_RADIO->EVENTS_READY = 0;
+    NRF_RADIO->EVENTS_END = 0;
+    NRF_RADIO->EVENTS_DISABLED = 0;
+
+    /* Enable shortcuts for transmit start/end. */
+    shortcuts = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk;
+    NRF_RADIO->SHORTS = shortcuts;
+    NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
+
+    /* Set transmitted payload length */
+    g_ble_phy_data.phy_tx_pyld_len = payload_len;
+
+    /* Set the PHY transition */
+    g_ble_phy_data.phy_transition = end_trans;
+
+    /* If we already started transmitting, abort it! */
+    state = NRF_RADIO->STATE;
+    if (state != RADIO_STATE_STATE_Tx) {
+        /* Copy data from mbuf into transmit buffer */
+        os_mbuf_copydata(txpdu, ble_hdr->txinfo.offset, payload_len, dptr);
+
+        /* Set phy state to transmitting and count packet statistics */
+        g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
+        STATS_INC(ble_phy_stats, tx_good);
+        STATS_INCN(ble_phy_stats, tx_bytes, payload_len + BLE_LL_PDU_HDR_LEN);
+        rc = BLE_ERR_SUCCESS;
+    } else {
+        ble_phy_disable();
+        STATS_INC(ble_phy_stats, tx_late);
+        rc = BLE_PHY_ERR_RADIO_STATE;
+    }
+
+    return rc;
+}
+
+/**
+ * ble phy txpwr set
+ *
+ * Set the transmit output power (in dBm).
+ *
+ * NOTE: If the output power specified is within the BLE limits but outside
+ * the chip limits, we "rail" the power level so we dont exceed the min/max
+ * chip values.
+ *
+ * @param dbm Power output in dBm.
+ *
+ * @return int 0: success; anything else is an error
+ */
+int
+ble_phy_txpwr_set(int dbm)
+{
+    /* Check valid range */
+    assert(dbm <= BLE_PHY_MAX_PWR_DBM);
+
+    /* "Rail" power level if outside supported range */
+    if (dbm > NRF_TX_PWR_MAX_DBM) {
+        dbm = NRF_TX_PWR_MAX_DBM;
+    } else {
+        if (dbm < NRF_TX_PWR_MIN_DBM) {
+            dbm = NRF_TX_PWR_MIN_DBM;
+        }
+    }
+
+    NRF_RADIO->TXPOWER = dbm;
+    g_ble_phy_data.phy_txpwr_dbm = dbm;
+
+    return 0;
+}
+
+/**
+ * ble phy txpwr round
+ *
+ * Get the rounded transmit output power (in dBm).
+ *
+ * @param dbm Power output in dBm.
+ *
+ * @return int Rounded power in dBm
+ */
+int ble_phy_txpower_round(int dbm)
+{
+    /* "Rail" power level if outside supported range */
+    if (dbm > NRF_TX_PWR_MAX_DBM) {
+        dbm = NRF_TX_PWR_MAX_DBM;
+    } else {
+        if (dbm < NRF_TX_PWR_MIN_DBM) {
+            dbm = NRF_TX_PWR_MIN_DBM;
+        }
+    }
+
+    return dbm;
+}
+
+/**
+ * ble phy set access addr
+ *
+ * Set access address.
+ *
+ * @param access_addr Access address
+ *
+ * @return int 0: success; PHY error code otherwise
+ */
+int
+ble_phy_set_access_addr(uint32_t access_addr)
+{
+    NRF_RADIO->BASE0 = (access_addr << 8);
+    NRF_RADIO->PREFIX0 = (NRF_RADIO->PREFIX0 & 0xFFFFFF00) | (access_addr >> 24);
+
+    g_ble_phy_data.phy_access_address = access_addr;
+
+    return 0;
+}
+
+/**
+ * ble phy txpwr get
+ *
+ * Get the transmit power.
+ *
+ * @return int  The current PHY transmit power, in dBm
+ */
+int
+ble_phy_txpwr_get(void)
+{
+    return g_ble_phy_data.phy_txpwr_dbm;
+}
+
+/**
+ * ble phy setchan
+ *
+ * Sets the logical frequency of the transceiver. The input parameter is the
+ * BLE channel index (0 to 39, inclusive). The NRF frequency register works like
+ * this: logical frequency = 2400 + FREQ (MHz).
+ *
+ * Thus, to get a logical frequency of 2402 MHz, you would program the
+ * FREQUENCY register to 2.
+ *
+ * @param chan This is the Data Channel Index or Advertising Channel index
+ *
+ * @return int 0: success; PHY error code otherwise
+ */
+int
+ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
+{
+    uint8_t freq;
+
+    assert(chan < BLE_PHY_NUM_CHANS);
+
+    /* Check for valid channel range */
+    if (chan >= BLE_PHY_NUM_CHANS) {
+        return BLE_PHY_ERR_INV_PARAM;
+    }
+
+    /* Get correct frequency */
+    if (chan < BLE_PHY_NUM_DATA_CHANS) {
+        if (chan < 11) {
+            /* Data channel 0 starts at 2404. 0 - 10 are contiguous */
+            freq = (BLE_PHY_DATA_CHAN0_FREQ_MHZ - 2400) +
+                   (BLE_PHY_CHAN_SPACING_MHZ * chan);
+        } else {
+            /* Data channel 11 starts at 2428. 0 - 10 are contiguous */
+            freq = (BLE_PHY_DATA_CHAN0_FREQ_MHZ - 2400) +
+                   (BLE_PHY_CHAN_SPACING_MHZ * (chan + 1));
+        }
+
+        /* Set current access address */
+        ble_phy_set_access_addr(access_addr);
+
+        /* Configure crcinit */
+        NRF_RADIO->CRCINIT = crcinit;
+    } else {
+        if (chan == 37) {
+            freq = BLE_PHY_CHAN_SPACING_MHZ;
+        } else if (chan == 38) {
+            /* This advertising channel is at 2426 MHz */
+            freq = BLE_PHY_CHAN_SPACING_MHZ * 13;
+        } else {
+            /* This advertising channel is at 2480 MHz */
+            freq = BLE_PHY_CHAN_SPACING_MHZ * 40;
+        }
+
+        /* Set current access address */
+        ble_phy_set_access_addr(access_addr);
+
+        /* Configure crcinit */
+        NRF_RADIO->CRCINIT = crcinit;
+    }
+
+    /* Set the frequency and the data whitening initial value */
+    g_ble_phy_data.phy_chan = chan;
+    NRF_RADIO->FREQUENCY = freq;
+    NRF_RADIO->DATAWHITEIV = chan;
+
+    ble_ll_log(BLE_LL_LOG_ID_PHY_SETCHAN, chan, freq, access_addr);
+
+    return 0;
+}
+
+/**
+ * Stop the timer used to count microseconds when using RTC for cputime
+ */
+void
+ble_phy_stop_usec_timer(void)
+{
+    NRF_TIMER0->TASKS_STOP = 1;
+    NRF_TIMER0->TASKS_SHUTDOWN = 1;
+    NRF_RTC0->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk;
+}
+
+/**
+ * ble phy disable irq and ppi
+ *
+ * This routine is to be called when reception was stopped due to either a
+ * wait for response timeout or a packet being received and the phy is to be
+ * restarted in receive mode. Generally, the disable routine is called to stop
+ * the phy.
+ */
+void
+ble_phy_disable_irq_and_ppi(void)
+{
+    NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+    NRF_RADIO->SHORTS = 0;
+    NRF_RADIO->TASKS_DISABLE = 1;
+    NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH20_Msk |
+          PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk |
+          PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk;
+    NVIC_ClearPendingIRQ(RADIO_IRQn);
+    g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+}
+
+void
+ble_phy_restart_rx(void)
+{
+    ble_phy_disable_irq_and_ppi();
+    ble_phy_rx();
+}
+
+/**
+ * ble phy disable
+ *
+ * Disables the PHY. This should be called when an event is over. It stops
+ * the usec timer (if used), disables interrupts, disables the RADIO, disables
+ * PPI and sets state to idle.
+ */
+void
+ble_phy_disable(void)
+{
+    ble_ll_log(BLE_LL_LOG_ID_PHY_DISABLE, g_ble_phy_data.phy_state, 0, 0);
+    ble_phy_stop_usec_timer();
+    ble_phy_disable_irq_and_ppi();
+}
+
+/* Gets the current access address */
+uint32_t ble_phy_access_addr_get(void)
+{
+    return g_ble_phy_data.phy_access_address;
+}
+
+/**
+ * Return the phy state
+ *
+ * @return int The current PHY state.
+ */
+int
+ble_phy_state_get(void)
+{
+    return g_ble_phy_data.phy_state;
+}
+
+/**
+ * Called to see if a reception has started
+ *
+ * @return int
+ */
+int
+ble_phy_rx_started(void)
+{
+    return g_ble_phy_data.phy_rx_started;
+}
+
+/**
+ * Return the transceiver state
+ *
+ * @return int transceiver state.
+ */
+uint8_t
+ble_phy_xcvr_state_get(void)
+{
+    uint32_t state;
+    state = NRF_RADIO->STATE;
+    return (uint8_t)state;
+}
+
+/**
+ * Called to return the maximum data pdu payload length supported by the
+ * phy. For this chip, if encryption is enabled, the maximum payload is 27
+ * bytes.
+ *
+ * @return uint8_t Maximum data channel PDU payload size supported
+ */
+uint8_t
+ble_phy_max_data_pdu_pyld(void)
+{
+    return BLE_LL_DATA_PDU_MAX_PYLD;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+void
+ble_phy_resolv_list_enable(void)
+{
+    NRF_AAR->NIRK = (uint32_t)g_nrf_num_irks;
+    g_ble_phy_data.phy_privacy = 1;
+}
+
+void
+ble_phy_resolv_list_disable(void)
+{
+    g_ble_phy_data.phy_privacy = 0;
+}
+#endif
+
+#ifdef BLE_XCVR_RFCLK
+void
+ble_phy_rfclk_enable(void)
+{
+    NRF_CLOCK->TASKS_HFCLKSTART = 1;
+}
+
+void
+ble_phy_rfclk_disable(void)
+{
+    NRF_CLOCK->TASKS_HFCLKSTOP = 1;
+}
+#endif
diff --git a/nimble/drivers/nrf52/syscfg.yml b/nimble/drivers/nrf52/syscfg.yml
new file mode 100644
index 0000000..b4088aa
--- /dev/null
+++ b/nimble/drivers/nrf52/syscfg.yml
@@ -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.
+#
+
+# Package: hw/drivers/nimble/nrf52
+
+syscfg.defs:
+    BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN:
+        description: >
+            This defines additional margin for T_IFS tolerance while in
+            RX on coded phy to allow maintaining connections with some
+            controllers that exceed proper T_IFS (150 usecs) by more
+            than allowed 2 usecs.
+            This value shall be only used for debugging purposes. It is
+            strongly recommended to keep this settings at default value
+            to ensure compliance with specification.
+        value: 0
+    BLE_PHY_DBG_TIME_TXRXEN_READY_PIN:
+        description: >
+            When set to proper GPIO pin number, this pin will be set
+            to high state when radio is enabled using PPI channels
+            20 or 21 and back to low state on radio EVENTS_READY.
+            This can be used to measure radio ram-up time.
+        value: -1
+
+    BLE_PHY_DBG_TIME_ADDRESS_END_PIN:
+        description: >
+            When set to proper GPIO pin number, this pin will be set
+            to high state on radio EVENTS_ADDRESS and back to low state
+            on radio EVENTS_END.
+            This can be used to measure radio pipeline delays.
+        value: -1
+
+    BLE_PHY_DBG_TIME_WFR_PIN:
+        description: >
+            When set to proper GPIO pin number, this pin will be set
+            to high state on radio EVENTS_RXREADY and back to low
+            state when wfr timer expires.
+            This can be used to check if wfr is calculated properly.
+        value: -1

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

[mynewt-nimble] 01/04: Add local copy of Tinycrypt

Posted by an...@apache.org.
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 359188d56db3fccd89a77ad4f3b0bd3b3bc110e5
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Wed Dec 6 09:46:43 2017 +0100

    Add local copy of Tinycrypt
    
    We will need this for building ported Nimble - in Mynewt we'll use the
    one included there.
---
 tinycrypt/AUTHORS                                  |  15 +
 tinycrypt/LICENSE                                  |  61 ++
 tinycrypt/README                                   |  71 ++
 tinycrypt/VERSION                                  |   1 +
 tinycrypt/documentation/tinycrypt.rst              | 352 ++++++++
 tinycrypt/include/tinycrypt/aes.h                  | 130 +++
 tinycrypt/include/tinycrypt/cbc_mode.h             | 151 ++++
 tinycrypt/include/tinycrypt/ccm_mode.h             | 211 +++++
 tinycrypt/include/tinycrypt/cmac_mode.h            | 194 +++++
 tinycrypt/include/tinycrypt/constants.h            |  61 ++
 tinycrypt/include/tinycrypt/ctr_mode.h             | 108 +++
 tinycrypt/include/tinycrypt/ctr_prng.h             | 166 ++++
 tinycrypt/include/tinycrypt/ecc.h                  | 545 ++++++++++++
 tinycrypt/include/tinycrypt/ecc_dh.h               | 131 +++
 tinycrypt/include/tinycrypt/ecc_dsa.h              | 139 +++
 .../include/tinycrypt/ecc_platform_specific.h      |  81 ++
 tinycrypt/include/tinycrypt/hmac.h                 | 139 +++
 tinycrypt/include/tinycrypt/hmac_prng.h            | 164 ++++
 tinycrypt/include/tinycrypt/sha256.h               | 129 +++
 tinycrypt/include/tinycrypt/utils.h                |  95 +++
 tinycrypt/src/aes_decrypt.c                        | 164 ++++
 tinycrypt/src/aes_encrypt.c                        | 191 +++++
 tinycrypt/src/cbc_mode.c                           | 114 +++
 tinycrypt/src/ccm_mode.c                           | 266 ++++++
 tinycrypt/src/cmac_mode.c                          | 254 ++++++
 tinycrypt/src/ctr_mode.c                           |  85 ++
 tinycrypt/src/ctr_prng.c                           | 283 +++++++
 tinycrypt/src/ecc.c                                | 942 +++++++++++++++++++++
 tinycrypt/src/ecc_dh.c                             | 200 +++++
 tinycrypt/src/ecc_dsa.c                            | 295 +++++++
 tinycrypt/src/ecc_platform_specific.c              | 105 +++
 tinycrypt/src/hmac.c                               | 148 ++++
 tinycrypt/src/hmac_prng.c                          | 212 +++++
 tinycrypt/src/sha256.c                             | 217 +++++
 tinycrypt/src/utils.c                              |  74 ++
 35 files changed, 6494 insertions(+)

diff --git a/tinycrypt/AUTHORS b/tinycrypt/AUTHORS
new file mode 100644
index 0000000..0a8e9f8
--- /dev/null
+++ b/tinycrypt/AUTHORS
@@ -0,0 +1,15 @@
+Architect: 
+Rafael Misoczki <ra...@intel.com>
+
+Open Source Maintainer: 
+Constanza Heath <co...@intel.com>
+Rafael Misoczki <ra...@intel.com>
+
+Contributors:
+Constanza Heath <co...@intel.com>
+Rafael Misoczki <ra...@intel.com> 
+Flavio Santes <fl...@intel.com>
+Jarkko Sakkinen <ja...@intel.com>
+Chris Morrison
+Marti Bolivar
+Colin Ian King
diff --git a/tinycrypt/LICENSE b/tinycrypt/LICENSE
new file mode 100644
index 0000000..2e1db51
--- /dev/null
+++ b/tinycrypt/LICENSE
@@ -0,0 +1,61 @@
+
+================================================================================
+
+                     TinyCrypt Cryptographic Library                       
+
+================================================================================
+
+          Copyright (c) 2017, Intel Corporation. All rights reserved.         
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+  - Redistributions of source code must retain the above copyright notice, this 
+      list of conditions and the following disclaimer.
+      
+  - Redistributions in binary form must reproduce the above copyright notice, 
+      this list of conditions and the following disclaimer in the documentation 
+      and/or other materials provided with the distribution.
+      
+  - Neither the name of the Intel Corporation nor the names of its contributors 
+      may be used to endorse or promote products derived from this software 
+      without specific prior written permission. 
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+================================================================================
+Copyright (c) 2014, Kenneth MacKay
+All rights reserved.
+
+https://github.com/kmackay/micro-ecc
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+================================================================================
diff --git a/tinycrypt/README b/tinycrypt/README
new file mode 100644
index 0000000..fb52c19
--- /dev/null
+++ b/tinycrypt/README
@@ -0,0 +1,71 @@
+
+================================================================================
+
+                     TinyCrypt Cryptographic Library
+
+================================================================================
+
+          Copyright (c) 2017, Intel Corporation. All rights reserved.         
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+  - Redistributions of source code must retain the above copyright notice, this 
+      list of conditions and the following disclaimer.
+      
+  - Redistributions in binary form must reproduce the above copyright notice, 
+      this list of conditions and the following disclaimer in the documentation 
+      and/or other materials provided with the distribution.
+      
+  - Neither the name of the Intel Corporation nor the names of its contributors 
+      may be used to endorse or promote products derived from this software 
+      without specific prior written permission. 
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+================================================================================
+
+Overview:
+
+The TinyCrypt Library provides an implementation for constrained devices of a 
+minimal set of standard cryptography primitives. 
+
+Please, ***SEE THE DOCUMENTATION*** folder for more information on the supported 
+cryptographic primitives and the limitations of TinyCrypt library. For usage,
+security and technicalities, please see the corresponding header file of each 
+cryptographic primitive. 
+
+================================================================================
+
+Organization:
+
+/lib: C source code of the cryptographic primitives.
+/lib/include/tinycrypt: C header files of the cryptographic primitives.
+/tests: Test vectors of the cryptographic primitives.
+/doc: Documentation of TinyCrypt. 
+
+================================================================================
+
+Building:
+
+1) In Makefile.conf set: 
+    - CFLAGS for compiler flags.
+    - CC for compiler.
+    - ENABLE_TESTS for enabling (true) or disabling (false) tests compilation.
+2) In lib/Makefile select the primitives required by your project.
+3) In tests/Makefile select the corresponding tests of the selected primitives.
+4) make 
+5) run tests in tests/
+
+================================================================================
+
diff --git a/tinycrypt/VERSION b/tinycrypt/VERSION
new file mode 100644
index 0000000..a45be46
--- /dev/null
+++ b/tinycrypt/VERSION
@@ -0,0 +1 @@
+0.2.8
diff --git a/tinycrypt/documentation/tinycrypt.rst b/tinycrypt/documentation/tinycrypt.rst
new file mode 100644
index 0000000..356c099
--- /dev/null
+++ b/tinycrypt/documentation/tinycrypt.rst
@@ -0,0 +1,352 @@
+
+TinyCrypt Cryptographic Library
+###############################
+Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+
+Overview
+********
+The TinyCrypt Library provides an implementation for targeting constrained devices
+with a minimal set of standard cryptography primitives, as listed below. To better
+serve applications targeting constrained devices, TinyCrypt implementations differ
+from the standard specifications (see the Important Remarks section for some
+important differences). Certain cryptographic primitives depend on other
+primitives, as mentioned in the list below.
+
+Aside from the Important Remarks section below, valuable information on the usage,
+security and technicalities of each cryptographic primitive are found in the
+corresponding header file.
+
+* SHA-256:
+
+  * Type of primitive: Hash function.
+  * Standard Specification: NIST FIPS PUB 180-4.
+  * Requires: --
+
+* HMAC-SHA256:
+
+  * Type of primitive: Message authentication code.
+  * Standard Specification: RFC 2104.
+  * Requires: SHA-256
+
+* HMAC-PRNG:
+
+  * Type of primitive: Pseudo-random number generator (256-bit strength).
+  * Standard Specification: NIST SP 800-90A.
+  * Requires: SHA-256 and HMAC-SHA256.
+
+* AES-128:
+
+  * Type of primitive: Block cipher.
+  * Standard Specification: NIST FIPS PUB 197.
+  * Requires: --
+
+* AES-CBC mode:
+
+  * Type of primitive: Encryption mode of operation.
+  * Standard Specification: NIST SP 800-38A.
+  * Requires: AES-128.
+
+* AES-CTR mode:
+
+  * Type of primitive: Encryption mode of operation.
+  * Standard Specification: NIST SP 800-38A.
+  * Requires: AES-128.
+
+* AES-CMAC mode:
+
+  * Type of primitive: Message authentication code.
+  * Standard Specification: NIST SP 800-38B.
+  * Requires: AES-128.
+
+* AES-CCM mode:
+
+  * Type of primitive: Authenticated encryption.
+  * Standard Specification: NIST SP 800-38C.
+  * Requires: AES-128.
+
+* CTR-PRNG:
+
+  * Type of primitive: Pseudo-random number generator (128-bit strength).
+  * Standard Specification: NIST SP 800-90A.
+  * Requires: AES-128.
+  
+* ECC-DH:
+
+  * Type of primitive: Key exchange based on curve NIST p-256.
+  * Standard Specification: RFC 6090.
+  * Requires: ECC auxiliary functions (ecc.h/c).
+
+* ECC-DSA:
+
+  * Type of primitive: Digital signature based on curve NIST p-256.
+  * Standard Specification: RFC 6090.
+  * Requires: ECC auxiliary functions (ecc.h/c).
+
+Design Goals
+************
+
+* Minimize the code size of each cryptographic primitive. This means minimize
+ the size of a platform-independent implementation, as presented in TinyCrypt.
+ Note that various applications may require further features, optimizations with
+ respect to other metrics and countermeasures for particular threats. These
+ peculiarities would increase the code size and thus are not considered here.
+
+* Minimize the dependencies among the cryptographic primitives. This means
+ that it is unnecessary to build and allocate object code for more primitives
+ than the ones strictly required by the intended application. In other words,
+ one can select and compile only the primitives required by the application.
+
+
+Important Remarks
+*****************
+
+The cryptographic implementations in TinyCrypt library have some limitations.
+Some of these limitations are inherent to the cryptographic primitives
+themselves, while others are specific to TinyCrypt. These limitations were accepted
+in order to meet its design goals (in special, minimal code size) and to better 
+serve applications targeting constrained devices in general. Some of these 
+limitations are discussed in-depth below.
+
+General Remarks
+***************
+
+* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the
+  variety of side-channel attacks, many of them only relevant to certain 
+  platforms. In this sense, instead of penalizing all library users with
+  side-channel countermeasures such as increasing the overall code size,
+  TinyCrypt only implements certain generic timing-attack countermeasures.
+
+Specific Remarks
+****************
+
+* SHA-256:
+
+  * The number of bits_hashed in the state is not checked for overflow. Note
+    however that this will only be a problem if you intend to hash more than
+    2^64 bits, which is an extremely large window.
+
+* HMAC:
+
+  * The HMAC verification process is assumed to be performed by the application.
+    This compares the computed tag with some given tag.
+    Note that conventional memory-comparison methods (such as memcmp function)
+    might be vulnerable to timing attacks; thus be sure to use a constant-time
+    memory comparison function (such as compare_constant_time
+    function provided in lib/utils.c).
+
+  * The tc_hmac_final function, responsible for computing the message tag,
+    cleans the state context before exiting. Thus, applications do not need to
+    clean the TCHmacState_t ctx after calling tc_hmac_final. This should not
+    be changed in future versions of the library as there are applications
+    currently relying on this good-practice/feature of TinyCrypt.
+
+* HMAC-PRNG:
+
+  * Before using HMAC-PRNG, you *must* find an entropy source to produce a seed.
+    PRNGs only stretch the seed into a seemingly random output of arbitrary
+    length. The security of the output is exactly equal to the
+    unpredictability of the seed.
+
+  * NIST SP 800-90A requires three items as seed material in the initialization
+    step: entropy seed, personalization and a nonce (which is not implemented).
+    TinyCrypt requires the personalization byte array and automatically creates
+    the entropy seed using a mandatory call to the re-seed function.
+
+* AES-128:
+
+  * The current implementation does not support other key-lengths (such as 256
+    bits). Note that if you need AES-256, it doesn't sound as though your
+    application is running in a constrained environment. AES-256 requires keys
+    twice the size as for AES-128, and the key schedule is 40% larger.
+
+* CTR mode:
+
+  * The AES-CTR mode limits the size of a data message they encrypt to 2^32
+    blocks. If you need to encrypt larger data sets, your application would
+    need to replace the key after 2^32 block encryptions.
+
+* CTR-PRNG:
+
+  * Before using CTR-PRNG, you *must* find an entropy source to produce a seed.
+    PRNGs only stretch the seed into a seemingly random output of arbitrary
+    length. The security of the output is exactly equal to the
+    unpredictability of the seed.
+
+* CBC mode:
+
+  * TinyCrypt CBC decryption assumes that the iv and the ciphertext are
+    contiguous (as produced by TinyCrypt CBC encryption). This allows for a
+    very efficient decryption algorithm that would not otherwise be possible.
+
+* CMAC mode:
+
+  * AES128-CMAC mode of operation offers 64 bits of security against collision
+    attacks. Note however that an external attacker cannot generate the tags
+    him/herself without knowing the MAC key. In this sense, to attack the
+    collision property of AES128-CMAC, an external attacker would need the
+    cooperation of the legal user to produce an exponentially high number of
+    tags (e.g. 2^64) to finally be able to look for collisions and benefit
+    from them. As an extra precaution, the current implementation allows to at
+    most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup
+    (allowing a new key to be set), as suggested in Appendix B of SP 800-38B.
+
+* CCM mode:
+
+  * There are a few tradeoffs for the selection of the parameters of CCM mode.
+    In special, there is a tradeoff between the maximum number of invocations
+    of CCM under a given key and the maximum payload length for those
+    invocations. Both things are related to the parameter 'q' of CCM mode. The
+    maximum number of invocations of CCM under a given key is determined by
+    the nonce size, which is: 15-q bytes. The maximum payload length for those
+    invocations is defined as 2^(8q) bytes.
+
+    To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2,
+    which is a quite reasonable choice for constrained applications. The
+    implications of this choice are:
+
+    The nonce size is: 13 bytes.
+
+    The maximum payload length is: 2^16 bytes = 65 KB.
+
+    The mac size parameter is an important parameter to estimate the security
+    against collision attacks (that aim at finding different messages that
+    produce the same authentication tag). TinyCrypt CCM implementation
+    accepts any even integer between 4 and 16, as suggested in SP 800-38C.
+
+  * TinyCrypt CCM implementation accepts associated data of any length between
+    0 and (2^16 - 2^8) = 65280 bytes.
+
+  * TinyCrypt CCM implementation accepts:
+
+        * Both non-empty payload and associated data (it encrypts and
+          authenticates the payload and only authenticates the associated data);
+
+        * Non-empty payload and empty associated data (it encrypts and
+          authenticates the payload);
+
+        * Non-empty associated data and empty payload (it degenerates to an
+          authentication-only mode on the associated data).
+
+   * RFC-3610, which also specifies CCM, presents a few relevant security
+     suggestions, such as: it is recommended for most applications to use a
+     mac size greater than 8. Besides, it is emphasized that the usage of the
+     same nonce for two different messages which are encrypted with the same
+     key obviously destroys the security properties of CCM mode.
+
+* ECC-DH and ECC-DSA:
+
+  * TinyCrypt ECC implementation is based on micro-ecc (see
+    https://github.com/kmackay/micro-ecc). In the original micro-ecc 
+    documentation, there is an important remark about the way integers are
+    represented:
+
+    "Integer representation: To reduce code size, all large integers are
+    represented using little-endian words - so the least significant word is
+    first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()'
+    functions to convert between the native integer representation and the
+    standardized octet representation."
+
+    Note that the assumed bit layout is: {31, 30, ..., 0}, {63, 62, ..., 32},
+    {95, 94, ..., 64}, {127, 126, ..., 96} for a very-long-integer (vli)
+    consisting of 4 unsigned integers (as an example).
+
+  * A cryptographically-secure PRNG function must be set (using uECC_set_rng())
+    before calling uECC_make_key() or uECC_sign().
+
+Examples of Applications
+************************
+It is possible to do useful cryptography with only the given small set of
+primitives. With this list of primitives it becomes feasible to support a range
+of cryptography usages:
+
+ * Measurement of code, data structures, and other digital artifacts (SHA256);
+
+ * Generate commitments (SHA256);
+
+ * Construct keys (HMAC-SHA256);
+
+ * Extract entropy from strings containing some randomness (HMAC-SHA256);
+
+ * Construct random mappings (HMAC-SHA256);
+
+ * Construct nonces and challenges (HMAC-PRNG, CTR-PRNG);
+
+ * Authenticate using a shared secret (HMAC-SHA256);
+
+ * Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG);
+
+ * Authenticated encryption (AES-128 + AES-CCM);
+
+ * Key-exchange (EC-DH);
+
+ * Digital signature (EC-DSA);
+
+Test Vectors
+************
+
+The library provides a test program for each cryptographic primitive (see 'test'
+folder). Besides illustrating how to use the primitives, these tests evaluate
+the correctness of the implementations by checking the results against
+well-known publicly validated test vectors.
+
+For the case of the HMAC-PRNG, due to the necessity of performing an extensive
+battery test to produce meaningful conclusions, we suggest the user to evaluate
+the unpredictability of the implementation by using the NIST Statistical Test
+Suite (see References).
+
+For the case of the EC-DH and EC-DSA implementations, most of the test vectors
+were obtained from the site of the NIST Cryptographic Algorithm Validation
+Program (CAVP), see References.
+
+References
+**********
+
+* `NIST FIPS PUB 180-4 (SHA-256)`_
+
+.. _NIST FIPS PUB 180-4 (SHA-256):
+   http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
+
+* `NIST FIPS PUB 197 (AES-128)`_
+
+.. _NIST FIPS PUB 197 (AES-128):
+   http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+
+* `NIST SP800-90A (HMAC-PRNG)`_
+
+.. _NIST SP800-90A (HMAC-PRNG):
+   http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
+
+* `NIST SP 800-38A (AES-CBC and AES-CTR)`_
+
+.. _NIST SP 800-38A (AES-CBC and AES-CTR):
+   http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+
+* `NIST SP 800-38B (AES-CMAC)`_
+
+.. _NIST SP 800-38B (AES-CMAC):
+   http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
+
+* `NIST SP 800-38C (AES-CCM)`_
+
+.. _NIST SP 800-38C (AES-CCM):
+    http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
+
+* `NIST Statistical Test Suite (useful for testing HMAC-PRNG)`_
+
+.. _NIST Statistical Test Suite (useful for testing HMAC-PRNG):
+   http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html
+
+* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_
+
+.. _NIST Cryptographic Algorithm Validation Program (CAVP) site:
+   http://csrc.nist.gov/groups/STM/cavp/
+
+* `RFC 2104 (HMAC-SHA256)`_
+
+.. _RFC 2104 (HMAC-SHA256):
+   https://www.ietf.org/rfc/rfc2104.txt
+
+* `RFC 6090 (ECC-DH and ECC-DSA)`_
+
+.. _RFC 6090 (ECC-DH and ECC-DSA):
+   https://www.ietf.org/rfc/rfc6090.txt
diff --git a/tinycrypt/include/tinycrypt/aes.h b/tinycrypt/include/tinycrypt/aes.h
new file mode 100644
index 0000000..b612213
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/aes.h
@@ -0,0 +1,130 @@
+/* aes.h - TinyCrypt interface to an AES-128 implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to an AES-128 implementation.
+ *
+ *  Overview:   AES-128 is a NIST approved block cipher specified in
+ *              FIPS 197. Block ciphers are deterministic algorithms that
+ *              perform a transformation specified by a symmetric key in fixed-
+ *              length data sets, also called blocks.
+ *
+ *  Security:   AES-128 provides approximately 128 bits of security.
+ *
+ *  Usage:      1) call tc_aes128_set_encrypt/decrypt_key to set the key.
+ *
+ *              2) call tc_aes_encrypt/decrypt to process the data.
+ */
+
+#ifndef __TC_AES_H__
+#define __TC_AES_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define Nb (4)  /* number of columns (32-bit words) comprising the state */
+#define Nk (4)  /* number of 32-bit words comprising the key */
+#define Nr (10) /* number of rounds */
+#define TC_AES_BLOCK_SIZE (Nb*Nk)
+#define TC_AES_KEY_SIZE (Nb*Nk)
+
+typedef struct tc_aes_key_sched_struct {
+	unsigned int words[Nb*(Nr+1)];
+} *TCAesKeySched_t;
+
+/**
+ *  @brief Set AES-128 encryption key
+ *  Uses key k to initialize s
+ *  @return  returns TC_CRYPTO_SUCCESS (1)
+ *           returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL
+ *  @note       This implementation skips the additional steps required for keys
+ *              larger than 128 bits, and must not be used for AES-192 or
+ *              AES-256 key schedule -- see FIPS 197 for details
+ *  @param      s IN/OUT -- initialized struct tc_aes_key_sched_struct
+ *  @param      k IN -- points to the AES key
+ */
+int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k);
+
+/**
+ *  @brief AES-128 Encryption procedure
+ *  Encrypts contents of in buffer into out buffer under key;
+ *              schedule s
+ *  @note Assumes s was initialized by aes_set_encrypt_key;
+ *              out and in point to 16 byte buffers
+ *  @return  returns TC_CRYPTO_SUCCESS (1)
+ *           returns TC_CRYPTO_FAIL (0) if: out == NULL or in == NULL or s == NULL
+ *  @param out IN/OUT -- buffer to receive ciphertext block
+ *  @param in IN -- a plaintext block to encrypt
+ *  @param s IN -- initialized AES key schedule
+ */
+int tc_aes_encrypt(uint8_t *out, const uint8_t *in, 
+		   const TCAesKeySched_t s);
+
+/**
+ *  @brief Set the AES-128 decryption key
+ *  Uses key k to initialize s
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL
+ *  @note       This is the implementation of the straightforward inverse cipher
+ *              using the cipher documented in FIPS-197 figure 12, not the
+ *              equivalent inverse cipher presented in Figure 15
+ *  @warning    This routine skips the additional steps required for keys larger
+ *              than 128, and must not be used for AES-192 or AES-256 key
+ *              schedule -- see FIPS 197 for details
+ *  @param s  IN/OUT -- initialized struct tc_aes_key_sched_struct
+ *  @param k  IN -- points to the AES key
+ */
+int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k);
+
+/**
+ *  @brief AES-128 Encryption procedure
+ *  Decrypts in buffer into out buffer under key schedule s
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if: out is NULL or in is NULL or s is NULL
+ *  @note   Assumes s was initialized by aes_set_encrypt_key
+ *          out and in point to 16 byte buffers
+ *  @param out IN/OUT -- buffer to receive ciphertext block
+ *  @param in IN -- a plaintext block to encrypt
+ *  @param s IN -- initialized AES key schedule
+ */
+int tc_aes_decrypt(uint8_t *out, const uint8_t *in, 
+		   const TCAesKeySched_t s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_AES_H__ */
diff --git a/tinycrypt/include/tinycrypt/cbc_mode.h b/tinycrypt/include/tinycrypt/cbc_mode.h
new file mode 100644
index 0000000..4a837fd
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/cbc_mode.h
@@ -0,0 +1,151 @@
+/* cbc_mode.h - TinyCrypt interface to a CBC mode implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to a CBC mode implementation.
+ *
+ *  Overview: CBC (for "cipher block chaining") mode is a NIST approved mode of
+ *            operation defined in SP 800-38a. It can be used with any block
+ *            cipher to provide confidentiality of strings whose lengths are
+ *            multiples of the block_size of the underlying block cipher.
+ *            TinyCrypt hard codes AES as the block cipher.
+ *
+ *  Security: CBC mode provides data confidentiality given that the maximum
+ *            number q of blocks encrypted under a single key satisfies
+ *            q < 2^63, which is not a practical constraint (it is considered a
+ *            good practice to replace the encryption when q == 2^56). CBC mode
+ *            provides NO data integrity.
+ *
+ *            CBC mode assumes that the IV value input into the
+ *            tc_cbc_mode_encrypt is randomly generated. The TinyCrypt library
+ *            provides HMAC-PRNG module, which generates suitable IVs. Other
+ *            methods for generating IVs are acceptable, provided that the
+ *            values of the IVs generated appear random to any adversary,
+ *            including someone with complete knowledge of the system design.
+ *
+ *            The randomness property on which CBC mode's security depends is
+ *            the unpredictability of the IV. Since it is unpredictable, this
+ *            means in practice that CBC mode requires that the IV is stored
+ *            somehow with the ciphertext in order to recover the plaintext.
+ *
+ *            TinyCrypt CBC encryption prepends the IV to the ciphertext,
+ *            because this affords a more efficient (few buffers) decryption.
+ *            Hence tc_cbc_mode_encrypt assumes the ciphertext buffer is always
+ *            16 bytes larger than the plaintext buffer.
+ *
+ *  Requires: AES-128
+ *
+ *  Usage:    1) call tc_cbc_mode_encrypt to encrypt data.
+ *
+ *            2) call tc_cbc_mode_decrypt to decrypt data.
+ *
+ */
+
+#ifndef __TC_CBC_MODE_H__
+#define __TC_CBC_MODE_H__
+
+#include <tinycrypt/aes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  @brief CBC encryption procedure
+ *  CBC encrypts inlen bytes of the in buffer into the out buffer
+ *  using the encryption key schedule provided, prepends iv to out
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                out == NULL or
+ *                in == NULL or
+ *                ctr == NULL or
+ *                sched == NULL or
+ *                inlen == 0 or
+ *                (inlen % TC_AES_BLOCK_SIZE) != 0 or
+ *                (outlen % TC_AES_BLOCK_SIZE) != 0 or
+ *                outlen != inlen + TC_AES_BLOCK_SIZE
+ *  @note Assumes: - sched has been configured by aes_set_encrypt_key
+ *              - iv contains a 16 byte random string
+ *              - out buffer is large enough to hold the ciphertext + iv
+ *              - out buffer is a contiguous buffer
+ *              - in holds the plaintext and is a contiguous buffer
+ *              - inlen gives the number of bytes in the in buffer
+ *  @param out IN/OUT -- buffer to receive the ciphertext
+ *  @param outlen IN -- length of ciphertext buffer in bytes
+ *  @param in IN -- plaintext to encrypt
+ *  @param inlen IN -- length of plaintext buffer in bytes
+ *  @param iv IN -- the IV for the this encrypt/decrypt
+ *  @param sched IN --  AES key schedule for this encrypt
+ */
+int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
+			unsigned int inlen, const uint8_t *iv,
+			const TCAesKeySched_t sched);
+
+/**
+ * @brief CBC decryption procedure
+ * CBC decrypts inlen bytes of the in buffer into the out buffer
+ * using the provided encryption key schedule
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *                out == NULL or
+ *                in == NULL or
+ *                sched == NULL or
+ *                inlen == 0 or
+ *                outlen == 0 or
+ *                (inlen % TC_AES_BLOCK_SIZE) != 0 or
+ *                (outlen % TC_AES_BLOCK_SIZE) != 0 or
+ *                outlen != inlen + TC_AES_BLOCK_SIZE
+ * @note Assumes:- in == iv + ciphertext, i.e. the iv and the ciphertext are
+ *                contiguous. This allows for a very efficient decryption
+ *                algorithm that would not otherwise be possible
+ *              - sched was configured by aes_set_decrypt_key
+ *              - out buffer is large enough to hold the decrypted plaintext
+ *              and is a contiguous buffer
+ *              - inlen gives the number of bytes in the in buffer
+ * @param out IN/OUT -- buffer to receive decrypted data
+ * @param outlen IN -- length of plaintext buffer in bytes
+ * @param in IN -- ciphertext to decrypt, including IV
+ * @param inlen IN -- length of ciphertext buffer in bytes
+ * @param iv IN -- the IV for the this encrypt/decrypt
+ * @param sched IN --  AES key schedule for this decrypt
+ *
+ */
+int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
+			unsigned int inlen, const uint8_t *iv,
+			const TCAesKeySched_t sched);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CBC_MODE_H__ */
diff --git a/tinycrypt/include/tinycrypt/ccm_mode.h b/tinycrypt/include/tinycrypt/ccm_mode.h
new file mode 100644
index 0000000..69c798e
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/ccm_mode.h
@@ -0,0 +1,211 @@
+/* ccm_mode.h - TinyCrypt interface to a CCM mode implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to a CCM mode implementation.
+ *
+ *  Overview: CCM (for "Counter with CBC-MAC") mode is a NIST approved mode of
+ *            operation defined in SP 800-38C.
+ *
+ *            TinyCrypt CCM implementation accepts:
+ *
+ *            1) Both non-empty payload and associated data (it encrypts and
+ *            authenticates the payload and also authenticates the associated
+ *            data);
+ *            2) Non-empty payload and empty associated data (it encrypts and
+ *            authenticates the payload);
+ *            3) Non-empty associated data and empty payload (it degenerates to
+ *            an authentication mode on the associated data).
+ *
+ *            TinyCrypt CCM implementation accepts associated data of any length
+ *            between 0 and (2^16 - 2^8) bytes.
+ *
+ *  Security: The mac length parameter is an important parameter to estimate the
+ *            security against collision attacks (that aim at finding different
+ *            messages that produce the same authentication tag). TinyCrypt CCM
+ *            implementation accepts any even integer between 4 and 16, as
+ *            suggested in SP 800-38C.
+ *
+ *            RFC-3610, which also specifies CCM, presents a few relevant
+ *            security suggestions, such as: it is recommended for most
+ *            applications to use a mac length greater than 8. Besides, the
+ *            usage of the same nonce for two different messages which are
+ *            encrypted with the same key destroys the security of CCM mode.
+ *
+ *  Requires: AES-128
+ *
+ *  Usage:    1) call tc_ccm_config to configure.
+ *
+ *            2) call tc_ccm_mode_encrypt to encrypt data and generate tag.
+ *
+ *            3) call tc_ccm_mode_decrypt to decrypt data and verify tag.
+ */
+
+#ifndef __TC_CCM_MODE_H__
+#define __TC_CCM_MODE_H__
+
+#include <tinycrypt/aes.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* max additional authenticated size in bytes: 2^16 - 2^8 = 65280 */
+#define TC_CCM_AAD_MAX_BYTES 0xff00
+
+/* max message size in bytes: 2^(8L) = 2^16 = 65536 */
+#define TC_CCM_PAYLOAD_MAX_BYTES 0x10000
+
+/* struct tc_ccm_mode_struct represents the state of a CCM computation */
+typedef struct tc_ccm_mode_struct {
+	TCAesKeySched_t sched; /* AES key schedule */
+	uint8_t *nonce; /* nonce required by CCM */
+	unsigned int mlen; /* mac length in bytes (parameter t in SP-800 38C) */
+} *TCCcmMode_t;
+
+/**
+ * @brief CCM configuration procedure
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                c == NULL or
+ *                sched == NULL or
+ *                nonce == NULL or
+ *                mlen != {4, 6, 8, 10, 12, 16}
+ * @param c -- CCM state
+ * @param sched IN -- AES key schedule
+ * @param nonce IN - nonce
+ * @param nlen -- nonce length in bytes
+ * @param mlen -- mac length in bytes (parameter t in SP-800 38C)
+ */
+int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
+		  unsigned int nlen, unsigned int mlen);
+
+/**
+ * @brief CCM tag generation and encryption procedure
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *                out == NULL or
+ *                c == NULL or
+ *                ((plen > 0) and (payload == NULL)) or
+ *                ((alen > 0) and (associated_data == NULL)) or
+ *                (alen >= TC_CCM_AAD_MAX_BYTES) or
+ *                (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or
+ *                (olen < plen + maclength)
+ *
+ * @param out OUT -- encrypted data
+ * @param olen IN -- output length in bytes
+ * @param associated_data IN -- associated data
+ * @param alen IN -- associated data length in bytes
+ * @param payload IN -- payload
+ * @param plen IN -- payload length in bytes
+ * @param c IN -- CCM state
+ *
+ * @note: out buffer should be at least (plen + c->mlen) bytes long.
+ *
+ * @note: The sequence b for encryption is formatted as follows:
+ *        b = [FLAGS | nonce | counter ], where:
+ *          FLAGS is 1 byte long
+ *          nonce is 13 bytes long
+ *          counter is 2 bytes long
+ *        The byte FLAGS is composed by the following 8 bits:
+ *          0-2 bits: used to represent the value of q-1
+ *          3-7 btis: always 0's
+ *
+ * @note: The sequence b for authentication is formatted as follows:
+ *        b = [FLAGS | nonce | length(mac length)], where:
+ *          FLAGS is 1 byte long
+ *          nonce is 13 bytes long
+ *          length(mac length) is 2 bytes long
+ *        The byte FLAGS is composed by the following 8 bits:
+ *          0-2 bits: used to represent the value of q-1
+ *          3-5 bits: mac length (encoded as: (mlen-2)/2)
+ *          6: Adata (0 if alen == 0, and 1 otherwise)
+ *          7: always 0
+ */
+int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
+			   	 const uint8_t *associated_data,
+			   	 unsigned int alen, const uint8_t *payload,
+				 unsigned int plen, TCCcmMode_t c);
+
+/**
+ * @brief CCM decryption and tag verification procedure
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *                out == NULL or
+ *                c == NULL or
+ *                ((plen > 0) and (payload == NULL)) or
+ *                ((alen > 0) and (associated_data == NULL)) or
+ *                (alen >= TC_CCM_AAD_MAX_BYTES) or
+ *                (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or
+ *                (olen < plen - c->mlen)
+ *
+ * @param out OUT -- decrypted data
+ * @param associated_data IN -- associated data
+ * @param alen IN -- associated data length in bytes
+ * @param payload IN -- payload
+ * @param plen IN -- payload length in bytes
+ * @param c IN -- CCM state
+ *
+ * @note: out buffer should be at least (plen - c->mlen) bytes long.
+ *
+ * @note: The sequence b for encryption is formatted as follows:
+ *        b = [FLAGS | nonce | counter ], where:
+ *          FLAGS is 1 byte long
+ *          nonce is 13 bytes long
+ *          counter is 2 bytes long
+ *        The byte FLAGS is composed by the following 8 bits:
+ *          0-2 bits: used to represent the value of q-1
+ *          3-7 btis: always 0's
+ *
+ * @note: The sequence b for authentication is formatted as follows:
+ *        b = [FLAGS | nonce | length(mac length)], where:
+ *          FLAGS is 1 byte long
+ *          nonce is 13 bytes long
+ *          length(mac length) is 2 bytes long
+ *        The byte FLAGS is composed by the following 8 bits:
+ *          0-2 bits: used to represent the value of q-1
+ *          3-5 bits: mac length (encoded as: (mlen-2)/2)
+ *          6: Adata (0 if alen == 0, and 1 otherwise)
+ *          7: always 0
+ */
+int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
+				   const uint8_t *associated_data,
+				   unsigned int alen, const uint8_t *payload, unsigned int plen,
+				   TCCcmMode_t c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CCM_MODE_H__ */
diff --git a/tinycrypt/include/tinycrypt/cmac_mode.h b/tinycrypt/include/tinycrypt/cmac_mode.h
new file mode 100644
index 0000000..f44b0a5
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/cmac_mode.h
@@ -0,0 +1,194 @@
+/*  cmac_mode.h -- interface to a CMAC implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to a CMAC implementation.
+ *
+ *  Overview: CMAC is defined NIST in SP 800-38B, and is the standard algorithm
+ *            for computing a MAC using a block cipher. It can compute the MAC
+ *            for a byte string of any length. It is distinguished from CBC-MAC
+ *            in the processing of the final message block; CMAC uses a
+ *            different technique to compute the final message block is full
+ *            size or only partial, while CBC-MAC uses the same technique for
+ *            both. This difference permits CMAC to be applied to variable
+ *            length messages, while all messages authenticated by CBC-MAC must
+ *            be the same length.
+ *
+ *  Security: AES128-CMAC mode of operation offers 64 bits of security against
+ *            collision attacks. Note however that an external attacker cannot
+ *            generate the tags him/herself without knowing the MAC key. In this
+ *            sense, to attack the collision property of AES128-CMAC, an
+ *            external attacker would need the cooperation of the legal user to
+ *            produce an exponentially high number of tags (e.g. 2^64) to
+ *            finally be able to look for collisions and benefit from them. As
+ *            an extra precaution, the current implementation allows to at most
+ *            2^48 calls to the tc_cmac_update function before re-calling
+ *            tc_cmac_setup (allowing a new key to be set), as suggested in
+ *            Appendix B of SP 800-38B.
+ *
+ *  Requires: AES-128
+ *
+ *  Usage:   This implementation provides a "scatter-gather" interface, so that
+ *           the CMAC value can be computed incrementally over a message
+ *           scattered in different segments throughout memory. Experience shows
+ *           this style of interface tends to minimize the burden of programming
+ *           correctly. Like all symmetric key operations, it is session
+ *           oriented.
+ *
+ *           To begin a CMAC session, use tc_cmac_setup to initialize a struct
+ *           tc_cmac_struct with encryption key and buffer. Our implementation
+ *           always assume that the AES key to be the same size as the block
+ *           cipher block size. Once setup, this data structure can be used for
+ *           many CMAC computations.
+ *
+ *           Once the state has been setup with a key, computing the CMAC of
+ *           some data requires three steps:
+ *
+ *           (1) first use tc_cmac_init to initialize a new CMAC computation.
+ *           (2) next mix all of the data into the CMAC computation state using
+ *               tc_cmac_update. If all of the data resides in a single data
+ *               segment then only one tc_cmac_update call is needed; if data
+ *               is scattered throughout memory in n data segments, then n calls
+ *               will be needed. CMAC IS ORDER SENSITIVE, to be able to detect
+ *               attacks that swap bytes, so the order in which data is mixed
+ *               into the state is critical!
+ *           (3) Once all of the data for a message has been mixed, use
+ *               tc_cmac_final to compute the CMAC tag value.
+ *
+ *           Steps (1)-(3) can be repeated as many times as you want to CMAC
+ *           multiple messages. A practical limit is 2^48 1K messages before you
+ *           have to change the key.
+ *
+ *           Once you are done computing CMAC with a key, it is a good idea to
+ *           destroy the state so an attacker cannot recover the key; use
+ *           tc_cmac_erase to accomplish this.
+ */
+
+#ifndef __TC_CMAC_MODE_H__
+#define __TC_CMAC_MODE_H__
+
+#include <tinycrypt/aes.h>
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* padding for last message block */
+#define TC_CMAC_PADDING 0x80
+
+/* struct tc_cmac_struct represents the state of a CMAC computation */
+typedef struct tc_cmac_struct {
+/* initialization vector */
+	uint8_t iv[TC_AES_BLOCK_SIZE];
+/* used if message length is a multiple of block_size bytes */
+	uint8_t K1[TC_AES_BLOCK_SIZE];
+/* used if message length isn't a multiple block_size bytes */
+	uint8_t K2[TC_AES_BLOCK_SIZE];
+/* where to put bytes that didn't fill a block */
+	uint8_t leftover[TC_AES_BLOCK_SIZE];
+/* identifies the encryption key */
+	unsigned int keyid;
+/* next available leftover location */
+	unsigned int leftover_offset;
+/* AES key schedule */
+	TCAesKeySched_t sched;
+/* calls to tc_cmac_update left before re-key */
+	uint64_t countdown;
+} *TCCmacState_t;
+
+/**
+ * @brief Configures the CMAC state to use the given AES key
+ * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *              s == NULL or
+ *              key == NULL
+ *
+ * @param s IN/OUT -- the state to set up
+ * @param key IN -- the key to use
+ * @param sched IN -- AES key schedule
+ */
+int tc_cmac_setup(TCCmacState_t s, const uint8_t *key,
+		      TCAesKeySched_t sched);
+
+/**
+ * @brief Erases the CMAC state
+ * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *              s == NULL
+ *
+ * @param s IN/OUT -- the state to erase
+ */
+int tc_cmac_erase(TCCmacState_t s);
+
+/**
+ * @brief Initializes a new CMAC computation
+ * @return returns TC_CRYPTO_SUCCESS (1) after having initialized the CMAC state
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *              s == NULL
+ *
+ * @param s IN/OUT -- the state to initialize
+ */
+int tc_cmac_init(TCCmacState_t s);
+
+/**
+ * @brief Incrementally computes CMAC over the next data segment
+ * @return returns TC_CRYPTO_SUCCESS (1) after successfully updating the CMAC state
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *              s == NULL or
+ *              if data == NULL when dlen > 0
+ *
+ * @param s IN/OUT -- the CMAC state
+ * @param data IN -- the next data segment to MAC
+ * @param dlen IN -- the length of data in bytes
+ */
+int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t dlen);
+
+/**
+ * @brief Generates the tag from the CMAC state
+ * @return returns TC_CRYPTO_SUCCESS (1) after successfully generating the tag
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *              tag == NULL or
+ *              s == NULL
+ *
+ * @param tag OUT -- the CMAC tag
+ * @param s IN -- CMAC state
+ */
+int tc_cmac_final(uint8_t *tag, TCCmacState_t s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CMAC_MODE_H__ */
diff --git a/tinycrypt/include/tinycrypt/constants.h b/tinycrypt/include/tinycrypt/constants.h
new file mode 100644
index 0000000..965490e
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/constants.h
@@ -0,0 +1,61 @@
+/* constants.h - TinyCrypt interface to constants */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to constants.
+ *
+ */
+
+#ifndef __TC_CONSTANTS_H__
+#define __TC_CONSTANTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define TC_CRYPTO_SUCCESS 1
+#define TC_CRYPTO_FAIL 0
+
+#define TC_ZERO_BYTE 0x00
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CONSTANTS_H__ */
diff --git a/tinycrypt/include/tinycrypt/ctr_mode.h b/tinycrypt/include/tinycrypt/ctr_mode.h
new file mode 100644
index 0000000..dc221f9
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/ctr_mode.h
@@ -0,0 +1,108 @@
+/* ctr_mode.h - TinyCrypt interface to CTR mode */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to CTR mode.
+ *
+ *  Overview:  CTR (pronounced "counter") mode is a NIST approved mode of
+ *             operation defined in SP 800-38a. It can be used with any
+ *             block cipher to provide confidentiality of strings of any
+ *             length. TinyCrypt hard codes AES128 as the block cipher.
+ *
+ *  Security:  CTR mode achieves confidentiality only if the counter value is
+ *             never reused with a same encryption key. If the counter is
+ *             repeated, than an adversary might be able to defeat the scheme.
+ *
+ *             A usual method to ensure different counter values refers to
+ *             initialize the counter in a given value (0, for example) and
+ *             increases it every time a new block is enciphered. This naturally
+ *             leaves to a limitation on the number q of blocks that can be
+ *             enciphered using a same key: q < 2^(counter size).
+ *
+ *             TinyCrypt uses a counter of 32 bits. This means that after 2^32
+ *             block encryptions, the counter will be reused (thus losing CBC
+ *             security). 2^32 block encryptions should be enough for most of
+ *             applications targeting constrained devices. Applications intended
+ *             to encrypt a larger number of blocks must replace the key after
+ *             2^32 block encryptions.
+ *
+ *             CTR mode provides NO data integrity.
+ *
+ *  Requires: AES-128
+ *
+ *  Usage:     1) call tc_ctr_mode to process the data to encrypt/decrypt.
+ *
+ */
+
+#ifndef __TC_CTR_MODE_H__
+#define __TC_CTR_MODE_H__
+
+#include <tinycrypt/aes.h>
+#include <tinycrypt/constants.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  @brief CTR mode encryption/decryption procedure.
+ *  CTR mode encrypts (or decrypts) inlen bytes from in buffer into out buffer
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                out == NULL or
+ *                in == NULL or
+ *                ctr == NULL or
+ *                sched == NULL or
+ *                inlen == 0 or
+ *                outlen == 0 or
+ *                inlen != outlen
+ *  @note Assumes:- The current value in ctr has NOT been used with sched
+ *              - out points to inlen bytes
+ *              - in points to inlen bytes
+ *              - ctr is an integer counter in littleEndian format
+ *              - sched was initialized by aes_set_encrypt_key
+ * @param out OUT -- produced ciphertext (plaintext)
+ * @param outlen IN -- length of ciphertext buffer in bytes
+ * @param in IN -- data to encrypt (or decrypt)
+ * @param inlen IN -- length of input data in bytes
+ * @param ctr IN/OUT -- the current counter value
+ * @param sched IN -- an initialized AES key schedule
+ */
+int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
+		unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CTR_MODE_H__ */
diff --git a/tinycrypt/include/tinycrypt/ctr_prng.h b/tinycrypt/include/tinycrypt/ctr_prng.h
new file mode 100644
index 0000000..9be06db
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/ctr_prng.h
@@ -0,0 +1,166 @@
+/* ctr_prng.h - TinyCrypt interface to a CTR-PRNG implementation */
+
+/*
+ * Copyright (c) 2016, Chris Morrison
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to a CTR-PRNG implementation.
+ *
+ *  Overview:   A pseudo-random number generator (PRNG) generates a sequence
+ *              of numbers that have a distribution close to the one expected
+ *              for a sequence of truly random numbers. The NIST Special
+ *              Publication 800-90A specifies several mechanisms to generate
+ *              sequences of pseudo random numbers, including the CTR-PRNG one
+ *              which is based on AES. TinyCrypt implements CTR-PRNG with
+ *              AES-128.
+ *
+ *  Security:   A cryptographically secure PRNG depends on the existence of an
+ *              entropy source to provide a truly random seed as well as the
+ *              security of the primitives used as the building blocks (AES-128
+ *              in this instance).
+ *
+ *  Requires:   - AES-128
+ *
+ *  Usage:      1) call tc_ctr_prng_init to seed the prng context
+ *
+ *              2) call tc_ctr_prng_reseed to mix in additional entropy into
+ *              the prng context
+ *
+ *              3) call tc_ctr_prng_generate to output the pseudo-random data
+ *
+ *              4) call tc_ctr_prng_uninstantiate to zero out the prng context
+ */
+
+#ifndef __TC_CTR_PRNG_H__
+#define __TC_CTR_PRNG_H__
+
+#include <tinycrypt/aes.h>
+
+#define TC_CTR_PRNG_RESEED_REQ -1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+	/* updated each time another BLOCKLEN_BYTES bytes are produced */
+	uint8_t V[TC_AES_BLOCK_SIZE]; 
+
+	/* updated whenever the PRNG is reseeded */
+	struct tc_aes_key_sched_struct key;
+
+	/* number of requests since initialization/reseeding */
+	uint64_t reseedCount;
+} TCCtrPrng_t;
+
+
+/**
+ *  @brief CTR-PRNG initialization procedure
+ *  Initializes prng context with entropy and personalization string (if any)
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                ctx == NULL,
+ *                entropy == NULL,
+ *                entropyLen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE)
+ *  @note       Only the first (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes of
+ *              both the entropy and personalization inputs are used -
+ *              supplying additional bytes has no effect.
+ *  @param ctx IN/OUT -- the PRNG context to initialize
+ *  @param entropy IN -- entropy used to seed the PRNG
+ *  @param entropyLen IN -- entropy length in bytes
+ *  @param personalization IN -- personalization string used to seed the PRNG
+ *  (may be null)
+ *  @param plen IN -- personalization length in bytes
+ *
+ */
+int tc_ctr_prng_init(TCCtrPrng_t * const ctx, 
+		     uint8_t const * const entropy,
+		     unsigned int entropyLen, 
+		     uint8_t const * const personalization,
+		     unsigned int pLen);
+
+/**
+ *  @brief CTR-PRNG reseed procedure
+ *  Mixes entropy and additional_input into the prng context
+ *  @return returns  TC_CRYPTO_SUCCESS (1)
+ *  returns TC_CRYPTO_FAIL (0) if:
+ *          ctx == NULL,
+ *          entropy == NULL,
+ *          entropylen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE)
+ *  @note It is better to reseed an existing prng context rather than
+ *        re-initialise, so that any existing entropy in the context is
+ *        presereved.  This offers some protection against undetected failures
+ *        of the entropy source.
+ *  @note Assumes tc_ctr_prng_init has been called for ctx
+ *  @param ctx IN/OUT -- the PRNG state
+ *  @param entropy IN -- entropy to mix into the prng
+ *  @param entropylen IN -- length of entropy in bytes
+ *  @param additional_input IN -- additional input to the prng (may be null)
+ *  @param additionallen IN -- additional input length in bytes
+ */
+int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx, 
+		       uint8_t const * const entropy,
+		       unsigned int entropyLen,
+		       uint8_t const * const additional_input,
+		       unsigned int additionallen);
+
+/**
+ *  @brief CTR-PRNG generate procedure
+ *  Generates outlen pseudo-random bytes into out buffer, updates prng
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CTR_PRNG_RESEED_REQ (-1) if a reseed is needed
+ *             returns TC_CRYPTO_FAIL (0) if:
+ *                ctx == NULL,
+ *                out == NULL,
+ *                outlen >= 2^16
+ *  @note Assumes tc_ctr_prng_init has been called for ctx
+ *  @param ctx IN/OUT -- the PRNG context
+ *  @param additional_input IN -- additional input to the prng (may be null)
+ *  @param additionallen IN -- additional input length in bytes
+ *  @param out IN/OUT -- buffer to receive output
+ *  @param outlen IN -- size of out buffer in bytes
+ */
+int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
+			 uint8_t const * const additional_input,
+			 unsigned int additionallen,
+			 uint8_t * const out,
+			 unsigned int outlen);
+
+/**
+ *  @brief CTR-PRNG uninstantiate procedure
+ *  Zeroes the internal state of the supplied prng context
+ *  @return none
+ *  @param ctx IN/OUT -- the PRNG context
+ */
+void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CTR_PRNG_H__ */
diff --git a/tinycrypt/include/tinycrypt/ecc.h b/tinycrypt/include/tinycrypt/ecc.h
new file mode 100644
index 0000000..8abc949
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/ecc.h
@@ -0,0 +1,545 @@
+/* ecc.h - TinyCrypt interface to common ECC functions */
+
+/* Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to common ECC functions.
+ *
+ *  Overview: This software is an implementation of common functions
+ *            necessary to elliptic curve cryptography. This implementation uses
+ *            curve NIST p-256.
+ *
+ *  Security: The curve NIST p-256 provides approximately 128 bits of security.
+ *
+ */
+
+#ifndef __TC_UECC_H__
+#define __TC_UECC_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Word size (4 bytes considering 32-bits architectures) */
+#define uECC_WORD_SIZE 4
+
+/* setting max number of calls to prng: */
+#ifndef uECC_RNG_MAX_TRIES
+#define uECC_RNG_MAX_TRIES 64
+#endif
+
+/* defining data types to store word and bit counts: */
+typedef int8_t wordcount_t;
+typedef int16_t bitcount_t;
+/* defining data type for comparison result: */
+typedef int8_t cmpresult_t;
+/* defining data type to store ECC coordinate/point in 32bits words: */
+typedef unsigned int uECC_word_t;
+/* defining data type to store an ECC coordinate/point in 64bits words: */
+typedef uint64_t uECC_dword_t;
+
+/* defining masks useful for ecc computations: */
+#define HIGH_BIT_SET 0x80000000
+#define uECC_WORD_BITS 32
+#define uECC_WORD_BITS_SHIFT 5
+#define uECC_WORD_BITS_MASK 0x01F
+
+/* Number of words of 32 bits to represent an element of the the curve p-256: */
+#define NUM_ECC_WORDS 8
+/* Number of bytes to represent an element of the the curve p-256: */
+#define NUM_ECC_BYTES (uECC_WORD_SIZE*NUM_ECC_WORDS)
+
+/* structure that represents an elliptic curve (e.g. p256):*/
+struct uECC_Curve_t;
+typedef const struct uECC_Curve_t * uECC_Curve;
+struct uECC_Curve_t {
+  wordcount_t num_words;
+  wordcount_t num_bytes;
+  bitcount_t num_n_bits;
+  uECC_word_t p[NUM_ECC_WORDS];
+  uECC_word_t n[NUM_ECC_WORDS];
+  uECC_word_t G[NUM_ECC_WORDS * 2];
+  uECC_word_t b[NUM_ECC_WORDS];
+  void (*double_jacobian)(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * Z1,
+	uECC_Curve curve);
+  void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
+  void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product);
+};
+
+/*
+ * @brief computes doubling of point ion jacobian coordinates, in place.
+ * @param X1 IN/OUT -- x coordinate
+ * @param Y1 IN/OUT -- y coordinate
+ * @param Z1 IN/OUT -- z coordinate
+ * @param curve IN -- elliptic curve
+ */
+void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
+			     uECC_word_t * Z1, uECC_Curve curve);
+
+/*
+ * @brief Computes x^3 + ax + b. result must not overlap x.
+ * @param result OUT -- x^3 + ax + b
+ * @param x IN -- value of x
+ * @param curve IN -- elliptic curve
+ */
+void x_side_default(uECC_word_t *result, const uECC_word_t *x,
+		    uECC_Curve curve);
+
+/*
+ * @brief Computes result = product % curve_p
+ * from http://www.nsa.gov/ia/_files/nist-routines.pdf
+ * @param result OUT -- product % curve_p
+ * @param product IN -- value to be reduced mod curve_p
+ */
+void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product);
+
+/* Bytes to words ordering: */
+#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e
+#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a
+#define BITS_TO_WORDS(num_bits) \
+	((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8))
+#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8)
+
+/* definition of curve NIST p-256: */
+static const struct uECC_Curve_t curve_secp256r1 = {
+	NUM_ECC_WORDS,
+	NUM_ECC_BYTES,
+	256, /* num_n_bits */ {
+		BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+		BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
+        	BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
+        	BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
+	}, {
+		BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
+            	BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
+            	BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+            	BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
+	}, {
+		BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
+                BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
+                BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
+                BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
+
+                BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
+                BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
+                BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
+                BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
+	}, {
+		BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
+                BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
+                BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
+                BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
+	},
+        &double_jacobian_default,
+        &x_side_default,
+        &vli_mmod_fast_secp256r1
+};
+
+uECC_Curve uECC_secp256r1(void);
+
+/*
+ * @brief Generates a random integer in the range 0 < random < top.
+ * Both random and top have num_words words.
+ * @param random OUT -- random integer in the range 0 < random < top
+ * @param top IN -- upper limit
+ * @param num_words IN -- number of words
+ * @return a random integer in the range 0 < random < top
+ */
+int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
+			     wordcount_t num_words);
+
+
+/* uECC_RNG_Function type
+ * The RNG function should fill 'size' random bytes into 'dest'. It should
+ * return 1 if 'dest' was filled with random data, or 0 if the random data could
+ * not be generated. The filled-in values should be either truly random, or from
+ * a cryptographically-secure PRNG.
+ *
+ * A correctly functioning RNG function must be set (using uECC_set_rng())
+ * before calling uECC_make_key() or uECC_sign().
+ *
+ * Setting a correctly functioning RNG function improves the resistance to
+ * side-channel attacks for uECC_shared_secret().
+ *
+ * A correct RNG function is set by default. If you are building on another
+ * POSIX-compliant system that supports /dev/random or /dev/urandom, you can
+ * define uECC_POSIX to use the predefined RNG.
+ */
+typedef int(*uECC_RNG_Function)(uint8_t *dest, unsigned int size);
+
+/*
+ * @brief Set the function that will be used to generate random bytes. The RNG
+ * function should return 1 if the random data was generated, or 0 if the random
+ * data could not be generated.
+ *
+ * @note On platforms where there is no predefined RNG function, this must be
+ * called before uECC_make_key() or uECC_sign() are used.
+ *
+ * @param rng_function IN -- function that will be used to generate random bytes
+ */
+void uECC_set_rng(uECC_RNG_Function rng_function);
+
+/*
+ * @brief provides current uECC_RNG_Function.
+ * @return Returns the function that will be used to generate random bytes.
+ */
+uECC_RNG_Function uECC_get_rng(void);
+
+/*
+ * @brief computes the size of a private key for the curve in bytes.
+ * @param curve IN -- elliptic curve
+ * @return size of a private key for the curve in bytes.
+ */
+int uECC_curve_private_key_size(uECC_Curve curve);
+
+/*
+ * @brief computes the size of a public key for the curve in bytes.
+ * @param curve IN -- elliptic curve
+ * @return the size of a public key for the curve in bytes.
+ */
+int uECC_curve_public_key_size(uECC_Curve curve);
+
+/*
+ * @brief Compute the corresponding public key for a private key.
+ * @param private_key IN -- The private key to compute the public key for
+ * @param public_key OUT -- Will be filled in with the corresponding public key
+ * @param curve
+ * @return Returns 1 if key was computed successfully, 0 if an error occurred.
+ */
+int uECC_compute_public_key(const uint8_t *private_key,
+			    uint8_t *public_key, uECC_Curve curve);
+
+/*
+ * @brief Compute public-key.
+ * @return corresponding public-key.
+ * @param result OUT -- public-key
+ * @param private_key IN -- private-key
+ * @param curve IN -- elliptic curve
+ */
+uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
+					uECC_word_t *private_key, uECC_Curve curve);
+
+/*
+ * @brief Regularize the bitcount for the private key so that attackers cannot
+ * use a side channel attack to learn the number of leading zeros.
+ * @return Regularized k
+ * @param k IN -- private-key
+ * @param k0 IN/OUT -- regularized k
+ * @param k1 IN/OUT -- regularized k
+ * @param curve IN -- elliptic curve
+ */
+uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
+			 uECC_word_t *k1, uECC_Curve curve);
+
+/*
+ * @brief Point multiplication algorithm using Montgomery's ladder with co-Z
+ * coordinates. See http://eprint.iacr.org/2011/338.pdf.
+ * @note Result may overlap point.
+ * @param result OUT -- returns scalar*point
+ * @param point IN -- elliptic curve point
+ * @param scalar IN -- scalar
+ * @param initial_Z IN -- initial value for z
+ * @param num_bits IN -- number of bits in scalar
+ * @param curve IN -- elliptic curve
+ */
+void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
+		   const uECC_word_t * scalar, const uECC_word_t * initial_Z,
+		   bitcount_t num_bits, uECC_Curve curve);
+
+/*
+ * @brief Constant-time comparison to zero - secure way to compare long integers
+ * @param vli IN -- very long integer
+ * @param num_words IN -- number of words in the vli
+ * @return 1 if vli == 0, 0 otherwise.
+ */
+uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words);
+
+/*
+ * @brief Check if 'point' is the point at infinity
+ * @param point IN -- elliptic curve point
+ * @param curve IN -- elliptic curve
+ * @return if 'point' is the point at infinity, 0 otherwise.
+ */
+uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve);
+
+/*
+ * @brief computes the sign of left - right, in constant time.
+ * @param left IN -- left term to be compared
+ * @param right IN -- right term to be compared
+ * @param num_words IN -- number of words
+ * @return the sign of left - right
+ */
+cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
+			 wordcount_t num_words);
+
+/*
+ * @brief computes sign of left - right, not in constant time.
+ * @note should not be used if inputs are part of a secret
+ * @param left IN -- left term to be compared
+ * @param right IN -- right term to be compared
+ * @param num_words IN -- number of words
+ * @return the sign of left - right
+ */
+cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right,
+				wordcount_t num_words);
+
+/*
+ * @brief Computes result = (left - right) % mod.
+ * @note Assumes that (left < mod) and (right < mod), and that result does not
+ * overlap mod.
+ * @param result OUT -- (left - right) % mod
+ * @param left IN -- leftright term in modular subtraction
+ * @param right IN -- right term in modular subtraction
+ * @param mod IN -- mod
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
+		     const uECC_word_t *right, const uECC_word_t *mod,
+		     wordcount_t num_words);
+
+/*
+ * @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or
+ * P => P', Q => P + Q
+ * @note assumes Input P = (x1, y1, Z), Q = (x2, y2, Z)
+ * @param X1 IN -- x coordinate of P
+ * @param Y1 IN -- y coordinate of P
+ * @param X2 IN -- x coordinate of Q
+ * @param Y2 IN -- y coordinate of Q
+ * @param curve IN -- elliptic curve
+ */
+void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2,
+	      uECC_word_t * Y2, uECC_Curve curve);
+
+/*
+ * @brief Computes (x1 * z^2, y1 * z^3)
+ * @param X1 IN -- previous x1 coordinate
+ * @param Y1 IN -- previous y1 coordinate
+ * @param Z IN -- z value
+ * @param curve IN -- elliptic curve
+ */
+void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
+	     uECC_Curve curve);
+
+/*
+ * @brief Check if bit is set.
+ * @return Returns nonzero if bit 'bit' of vli is set.
+ * @warning It is assumed that the value provided in 'bit' is within the
+ * boundaries of the word-array 'vli'.
+ * @note The bit ordering layout assumed for vli is: {31, 30, ..., 0},
+ * {63, 62, ..., 32}, {95, 94, ..., 64}, {127, 126,..., 96} for a vli consisting
+ * of 4 uECC_word_t elements.
+ */
+uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit);
+
+/*
+ * @brief Computes result = product % mod, where product is 2N words long.
+ * @param result OUT -- product % mod
+ * @param mod IN -- module
+ * @param num_words IN -- number of words
+ * @warning Currently only designed to work for curve_p or curve_n.
+ */
+void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
+		   const uECC_word_t *mod, wordcount_t num_words);
+
+/*
+ * @brief Computes modular product (using curve->mmod_fast)
+ * @param result OUT -- (left * right) mod % curve_p
+ * @param left IN -- left term in product
+ * @param right IN -- right term in product
+ * @param curve IN -- elliptic curve
+ */
+void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
+			   const uECC_word_t *right, uECC_Curve curve);
+
+/*
+ * @brief Computes result = left - right.
+ * @note Can modify in place.
+ * @param result OUT -- left - right
+ * @param left IN -- left term in subtraction
+ * @param right IN -- right term in subtraction
+ * @param num_words IN -- number of words
+ * @return borrow
+ */
+uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
+			 const uECC_word_t *right, wordcount_t num_words);
+
+/*
+ * @brief Constant-time comparison function(secure way to compare long ints)
+ * @param left IN -- left term in comparison
+ * @param right IN -- right term in comparison
+ * @param num_words IN -- number of words
+ * @return Returns 0 if left == right, 1 otherwise.
+ */
+uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
+			   wordcount_t num_words);
+
+/*
+ * @brief Computes (left * right) % mod
+ * @param result OUT -- (left * right) % mod
+ * @param left IN -- left term in product
+ * @param right IN -- right term in product
+ * @param mod IN -- mod
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
+		      const uECC_word_t *right, const uECC_word_t *mod,
+	              wordcount_t num_words);
+
+/*
+ * @brief Computes (1 / input) % mod
+ * @note All VLIs are the same size.
+ * @note See "Euclid's GCD to Montgomery Multiplication to the Great Divide"
+ * @param result OUT -- (1 / input) % mod
+ * @param input IN -- value to be modular inverted
+ * @param mod IN -- mod
+ * @param num_words -- number of words
+ */
+void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
+		     const uECC_word_t *mod, wordcount_t num_words);
+
+/*
+ * @brief Sets dest = src.
+ * @param dest OUT -- destination buffer
+ * @param src IN --  origin buffer
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
+		  wordcount_t num_words);
+
+/*
+ * @brief Computes (left + right) % mod.
+ * @note Assumes that (left < mod) and right < mod), and that result does not
+ * overlap mod.
+ * @param result OUT -- (left + right) % mod.
+ * @param left IN -- left term in addition
+ * @param right IN -- right term in addition
+ * @param mod IN -- mod
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_modAdd(uECC_word_t *result,  const uECC_word_t *left,
+    		     const uECC_word_t *right, const uECC_word_t *mod,
+   		     wordcount_t num_words);
+
+/*
+ * @brief Counts the number of bits required to represent vli.
+ * @param vli IN -- very long integer
+ * @param max_words IN -- number of words
+ * @return number of bits in given vli
+ */
+bitcount_t uECC_vli_numBits(const uECC_word_t *vli, 
+			    const wordcount_t max_words);
+
+/*
+ * @brief Erases (set to 0) vli
+ * @param vli IN -- very long integer
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words);
+
+/*
+ * @brief check if it is a valid point in the curve
+ * @param point IN -- point to be checked
+ * @param curve IN -- elliptic curve
+ * @return 0 if point is valid
+ * @exception returns -1 if it is a point at infinity
+ * @exception returns -2 if x or y is smaller than p,
+ * @exception returns -3 if y^2 != x^3 + ax + b.
+ */
+int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve);
+
+/*
+ * @brief Check if a public key is valid.
+ * @param public_key IN -- The public key to be checked.
+ * @return returns 0 if the public key is valid
+ * @exception returns -1 if it is a point at infinity
+ * @exception returns -2 if x or y is smaller than p,
+ * @exception returns -3 if y^2 != x^3 + ax + b.
+ * @exception returns -4 if public key is the group generator.
+ *
+ * @note Note that you are not required to check for a valid public key before
+ * using any other uECC functions. However, you may wish to avoid spending CPU
+ * time computing a shared secret or verifying a signature using an invalid
+ * public key.
+ */
+int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve);
+
+ /*
+  * @brief Converts an integer in uECC native format to big-endian bytes.
+  * @param bytes OUT -- bytes representation
+  * @param num_bytes IN -- number of bytes
+  * @param native IN -- uECC native representation
+  */
+void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
+    			    const unsigned int *native);
+
+/*
+ * @brief Converts big-endian bytes to an integer in uECC native format.
+ * @param native OUT -- uECC native representation
+ * @param bytes IN -- bytes representation
+ * @param num_bytes IN -- number of bytes
+ */
+void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
+			    int num_bytes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_UECC_H__ */
diff --git a/tinycrypt/include/tinycrypt/ecc_dh.h b/tinycrypt/include/tinycrypt/ecc_dh.h
new file mode 100644
index 0000000..b828e19
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/ecc_dh.h
@@ -0,0 +1,131 @@
+/* ecc_dh.h - TinyCrypt interface to EC-DH implementation */
+
+/*
+ * Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to EC-DH implementation.
+ *
+ *  Overview: This software is an implementation of EC-DH. This implementation
+ *            uses curve NIST p-256.
+ *
+ *  Security: The curve NIST p-256 provides approximately 128 bits of security.
+ */
+
+#ifndef __TC_ECC_DH_H__
+#define __TC_ECC_DH_H__
+
+#include <tinycrypt/ecc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Create a public/private key pair.
+ * @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully
+ *         returns TC_CRYPTO_FAIL (0) if error while generating key pair
+ *
+ * @param p_public_key OUT -- Will be filled in with the public key. Must be at
+ * least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key
+ * must be 64 bytes long.
+ * @param p_private_key OUT -- Will be filled in with the private key. Must be as
+ * long as the curve order (for secp256r1, p_private_key must be 32 bytes long).
+ *
+ * @note side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ * @warning A cryptographically-secure PRNG function must be set (using
+ * uECC_set_rng()) before calling uECC_make_key().
+ */
+int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key, uECC_Curve curve);
+
+#ifdef ENABLE_TESTS
+
+/**
+ * @brief Create a public/private key pair given a specific d.
+ *
+ * @note THIS FUNCTION SHOULD BE CALLED ONLY FOR TEST PURPOSES. Refer to
+ * uECC_make_key() function for real applications.
+ */
+int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key,
+    			 unsigned int *d, uECC_Curve curve);
+#endif
+
+/**
+ * @brief Compute a shared secret given your secret key and someone else's
+ * public key.
+ * @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully
+ *         returns TC_CRYPTO_FAIL (0) otherwise
+ *
+ * @param p_secret OUT -- Will be filled in with the shared secret value. Must be
+ * the same size as the curve size (for curve secp256r1, secret must be 32 bytes
+ * long.
+ * @param p_public_key IN -- The public key of the remote party.
+ * @param p_private_key IN -- Your private key.
+ *
+ * @warning It is recommended to use the output of uECC_shared_secret() as the
+ * input of a recommended Key Derivation Function (see NIST SP 800-108) in
+ * order to produce a cryptographically secure symmetric key.
+ */
+int uECC_shared_secret(const uint8_t *p_public_key, const uint8_t *p_private_key,
+		       uint8_t *p_secret, uECC_Curve curve);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_ECC_DH_H__ */
diff --git a/tinycrypt/include/tinycrypt/ecc_dsa.h b/tinycrypt/include/tinycrypt/ecc_dsa.h
new file mode 100644
index 0000000..aca00bc
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/ecc_dsa.h
@@ -0,0 +1,139 @@
+/* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */
+
+/*
+ * Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to EC-DSA implementation.
+ *
+ *  Overview: This software is an implementation of EC-DSA. This implementation
+ *            uses curve NIST p-256.
+ *
+ *  Security: The curve NIST p-256 provides approximately 128 bits of security.
+ *
+ *  Usage:  - To sign: Compute a hash of the data you wish to sign (SHA-2 is
+ *          recommended) and pass it in to ecdsa_sign function along with your
+ *          private key and a random number. You must use a new non-predictable
+ *          random number to generate each new signature.
+ *          - To verify a signature: Compute the hash of the signed data using
+ *          the same hash as the signer and pass it to this function along with
+ *          the signer's public key and the signature values (r and s).
+ */
+
+#ifndef __TC_ECC_DSA_H__
+#define __TC_ECC_DSA_H__
+
+#include <tinycrypt/ecc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Generate an ECDSA signature for a given hash value.
+ * @return returns TC_CRYPTO_SUCCESS (1) if the signature generated successfully
+ *         returns TC_CRYPTO_FAIL (0) if an error occurred.
+ *
+ * @param p_private_key IN -- Your private key.
+ * @param p_message_hash IN -- The hash of the message to sign.
+ * @param p_hash_size IN -- The size of p_message_hash in bytes.
+ * @param p_signature OUT -- Will be filled in with the signature value. Must be
+ * at least 2 * curve size long (for secp256r1, signature must be 64 bytes long).
+ *
+ * @warning A cryptographically-secure PRNG function must be set (using
+ * uECC_set_rng()) before calling uECC_sign().
+ * @note Usage: Compute a hash of the data you wish to sign (SHA-2 is
+ * recommended) and pass it in to this function along with your private key.
+ * @note side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash,
+	      unsigned p_hash_size, uint8_t *p_signature, uECC_Curve curve);
+
+#ifdef ENABLE_TESTS
+/*
+ * THIS FUNCTION SHOULD BE CALLED FOR TEST PURPOSES ONLY.
+ * Refer to uECC_sign() function for real applications.
+ */
+int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
+		     unsigned int hash_size, uECC_word_t *k, uint8_t *signature,
+		     uECC_Curve curve);
+#endif
+
+/**
+ * @brief Verify an ECDSA signature.
+ * @return returns TC_SUCCESS (1) if the signature is valid
+ * 	   returns TC_FAIL (0) if the signature is invalid.
+ *
+ * @param p_public_key IN -- The signer's public key.
+ * @param p_message_hash IN -- The hash of the signed data.
+ * @param p_hash_size IN -- The size of p_message_hash in bytes.
+ * @param p_signature IN -- The signature values.
+ *
+ * @note Usage: Compute the hash of the signed data using the same hash as the
+ * signer and pass it to this function along with the signer's public key and
+ * the signature values (hash_size and signature).
+ */
+int uECC_verify(const uint8_t *p_public_key, const uint8_t *p_message_hash,
+		unsigned int p_hash_size, const uint8_t *p_signature, uECC_Curve curve);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_ECC_DSA_H__ */
diff --git a/tinycrypt/include/tinycrypt/ecc_platform_specific.h b/tinycrypt/include/tinycrypt/ecc_platform_specific.h
new file mode 100644
index 0000000..a55adf4
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/ecc_platform_specific.h
@@ -0,0 +1,81 @@
+/*  uECC_platform_specific.h - Interface to platform specific functions*/
+
+/* Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.*/
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  uECC_platform_specific.h -- Interface to platform specific functions
+ */
+
+#ifndef __UECC_PLATFORM_SPECIFIC_H_
+#define __UECC_PLATFORM_SPECIFIC_H_
+
+/*
+ * The RNG function should fill 'size' random bytes into 'dest'. It should
+ * return 1 if 'dest' was filled with random data, or 0 if the random data could
+ * not be generated. The filled-in values should be either truly random, or from
+ * a cryptographically-secure PRNG.
+ *
+ * A cryptographically-secure PRNG function must be set (using uECC_set_rng())
+ * before calling uECC_make_key() or uECC_sign().
+ *
+ * Setting a cryptographically-secure PRNG function improves the resistance to
+ * side-channel attacks for uECC_shared_secret().
+ *
+ * A correct PRNG function is set by default (default_RNG_defined = 1) and works
+ * for some platforms, such as Unix and Linux. For other platforms, you may need
+ * to provide another PRNG function.
+*/
+#define default_RNG_defined 0
+
+int default_CSPRNG(uint8_t *dest, unsigned int size);
+
+#endif /* __UECC_PLATFORM_SPECIFIC_H_ */
diff --git a/tinycrypt/include/tinycrypt/hmac.h b/tinycrypt/include/tinycrypt/hmac.h
new file mode 100644
index 0000000..3a08149
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/hmac.h
@@ -0,0 +1,139 @@
+/* hmac.h - TinyCrypt interface to an HMAC implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to an HMAC implementation.
+ *
+ *  Overview:   HMAC is a message authentication code based on hash functions.
+ *              TinyCrypt hard codes SHA-256 as the hash function. A message
+ *              authentication code based on hash functions is also called a
+ *              keyed cryptographic hash function since it performs a
+ *              transformation specified by a key in an arbitrary length data
+ *              set into a fixed length data set (also called tag).
+ *
+ *  Security:   The security of the HMAC depends on the length of the key and
+ *              on the security of the hash function. Note that HMAC primitives
+ *              are much less affected by collision attacks than their
+ *              corresponding hash functions.
+ *
+ *  Requires:   SHA-256
+ *
+ *  Usage:      1) call tc_hmac_set_key to set the HMAC key.
+ *
+ *              2) call tc_hmac_init to initialize a struct hash_state before
+ *              processing the data.
+ *
+ *              3) call tc_hmac_update to process the next input segment;
+ *              tc_hmac_update can be called as many times as needed to process
+ *              all of the segments of the input; the order is important.
+ *
+ *              4) call tc_hmac_final to out put the tag.
+ */
+
+#ifndef __TC_HMAC_H__
+#define __TC_HMAC_H__
+
+#include <tinycrypt/sha256.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct tc_hmac_state_struct {
+	/* the internal state required by h */
+	struct tc_sha256_state_struct hash_state;
+	/* HMAC key schedule */
+	uint8_t key[2*TC_SHA256_BLOCK_SIZE];
+};
+typedef struct tc_hmac_state_struct *TCHmacState_t;
+
+/**
+ *  @brief HMAC set key procedure
+ *  Configures ctx to use key
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if
+ *                ctx == NULL or
+ *                key == NULL or
+ *                key_size == 0
+ * @param ctx IN/OUT -- the struct tc_hmac_state_struct to initial
+ * @param key IN -- the HMAC key to configure
+ * @param key_size IN -- the HMAC key size
+ */
+int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
+		    unsigned int key_size);
+
+/**
+ * @brief HMAC init procedure
+ * Initializes ctx to begin the next HMAC operation
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ *         returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
+ * @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to init
+ */
+int tc_hmac_init(TCHmacState_t ctx);
+
+/**
+ *  @brief HMAC update procedure
+ *  Mixes data_length bytes addressed by data into state
+ *  @return returns TC_CRYPTO_SUCCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
+ *  @note Assumes state has been initialized by tc_hmac_init
+ *  @param ctx IN/OUT -- state of HMAC computation so far
+ *  @param data IN -- data to incorporate into state
+ *  @param data_length IN -- size of data in bytes
+ */
+int tc_hmac_update(TCHmacState_t ctx, const void *data,
+		   unsigned int data_length);
+
+/**
+ *  @brief HMAC final procedure
+ *  Writes the HMAC tag into the tag buffer
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                tag == NULL or
+ *                ctx == NULL or
+ *                key == NULL or
+ *                taglen != TC_SHA256_DIGEST_SIZE
+ *  @note ctx is erased before exiting. This should never be changed/removed.
+ *  @note Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes
+ *  state has been initialized by tc_hmac_init
+ *  @param tag IN/OUT -- buffer to receive computed HMAC tag
+ *  @param taglen IN -- size of tag in bytes
+ *  @param ctx IN/OUT -- the HMAC state for computing tag
+ */
+int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__TC_HMAC_H__*/
diff --git a/tinycrypt/include/tinycrypt/hmac_prng.h b/tinycrypt/include/tinycrypt/hmac_prng.h
new file mode 100644
index 0000000..ad12cbb
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/hmac_prng.h
@@ -0,0 +1,164 @@
+/* hmac_prng.h - TinyCrypt interface to an HMAC-PRNG implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to an HMAC-PRNG implementation.
+ *
+ *  Overview:   A pseudo-random number generator (PRNG) generates a sequence
+ *              of numbers that have a distribution close to the one expected
+ *              for a sequence of truly random numbers. The NIST Special
+ *              Publication 800-90A specifies several mechanisms to generate
+ *              sequences of pseudo random numbers, including the HMAC-PRNG one
+ *              which is based on HMAC. TinyCrypt implements HMAC-PRNG with
+ *              certain modifications from the NIST SP 800-90A spec.
+ *
+ *  Security:   A cryptographically secure PRNG depends on the existence of an
+ *              entropy source to provide a truly random seed as well as the
+ *              security of the primitives used as the building blocks (HMAC and
+ *              SHA256, for TinyCrypt).
+ *
+ *              The NIST SP 800-90A standard tolerates a null personalization,
+ *              while TinyCrypt requires a non-null personalization. This is
+ *              because a personalization string (the host name concatenated
+ *              with a time stamp, for example) is easily computed and might be
+ *              the last line of defense against failure of the entropy source.
+ *
+ *  Requires:   - SHA-256
+ *              - HMAC
+ *
+ *  Usage:      1) call tc_hmac_prng_init to set the HMAC key and process the
+ *              personalization data.
+ *
+ *              2) call tc_hmac_prng_reseed to process the seed and additional
+ *              input.
+ *
+ *              3) call tc_hmac_prng_generate to out put the pseudo-random data.
+ */
+
+#ifndef __TC_HMAC_PRNG_H__
+#define __TC_HMAC_PRNG_H__
+
+#include <tinycrypt/sha256.h>
+#include <tinycrypt/hmac.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TC_HMAC_PRNG_RESEED_REQ -1
+
+struct tc_hmac_prng_struct {
+	/* the HMAC instance for this PRNG */
+	struct tc_hmac_state_struct h;
+	/* the PRNG key */
+	uint8_t key[TC_SHA256_DIGEST_SIZE];
+	/* PRNG state */
+	uint8_t v[TC_SHA256_DIGEST_SIZE];
+	/* calls to tc_hmac_prng_generate left before re-seed */
+	unsigned int countdown;
+};
+
+typedef struct tc_hmac_prng_struct *TCHmacPrng_t;
+
+/**
+ *  @brief HMAC-PRNG initialization procedure
+ *  Initializes prng with personalization, disables tc_hmac_prng_generate
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                prng == NULL,
+ *                personalization == NULL,
+ *                plen > MAX_PLEN
+ *  @note Assumes: - personalization != NULL.
+ *              The personalization is a platform unique string (e.g., the host
+ *              name) and is the last line of defense against failure of the
+ *              entropy source
+ *  @warning    NIST SP 800-90A specifies 3 items as seed material during
+ *              initialization: entropy seed, personalization, and an optional
+ *              nonce. TinyCrypts requires instead a non-null personalization
+ *              (which is easily computed) and indirectly requires an entropy
+ *              seed (since the reseed function is mandatorily called after
+ *              init)
+ *  @param prng IN/OUT -- the PRNG state to initialize
+ *  @param personalization IN -- personalization string
+ *  @param plen IN -- personalization length in bytes
+ */
+int tc_hmac_prng_init(TCHmacPrng_t prng,
+		      const uint8_t *personalization,
+		      unsigned int plen);
+
+/**
+ *  @brief HMAC-PRNG reseed procedure
+ *  Mixes seed into prng, enables tc_hmac_prng_generate
+ *  @return returns  TC_CRYPTO_SUCCESS (1)
+ *  	    returns TC_CRYPTO_FAIL (0) if:
+ *          prng == NULL,
+ *          seed == NULL,
+ *          seedlen < MIN_SLEN,
+ *          seendlen > MAX_SLEN,
+ *          additional_input != (const uint8_t *) 0 && additionallen == 0,
+ *          additional_input != (const uint8_t *) 0 && additionallen > MAX_ALEN
+ *  @note Assumes:- tc_hmac_prng_init has been called for prng
+ *              - seed has sufficient entropy.
+ *
+ *  @param prng IN/OUT -- the PRNG state
+ *  @param seed IN -- entropy to mix into the prng
+ *  @param seedlen IN -- length of seed in bytes
+ *  @param additional_input IN -- additional input to the prng
+ *  @param additionallen IN -- additional input length in bytes
+ */
+int tc_hmac_prng_reseed(TCHmacPrng_t prng, const uint8_t *seed,
+			unsigned int seedlen, const uint8_t *additional_input,
+			unsigned int additionallen);
+
+/**
+ *  @brief HMAC-PRNG generate procedure
+ *  Generates outlen pseudo-random bytes into out buffer, updates prng
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_HMAC_PRNG_RESEED_REQ (-1) if a reseed is needed
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                out == NULL,
+ *                prng == NULL,
+ *                outlen == 0,
+ *                outlen >= MAX_OUT
+ *  @note Assumes tc_hmac_prng_init has been called for prng
+ *  @param out IN/OUT -- buffer to receive output
+ *  @param outlen IN -- size of out buffer in bytes
+ *  @param prng IN/OUT -- the PRNG state
+ */
+int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_HMAC_PRNG_H__ */
diff --git a/tinycrypt/include/tinycrypt/sha256.h b/tinycrypt/include/tinycrypt/sha256.h
new file mode 100644
index 0000000..af5e8ba
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/sha256.h
@@ -0,0 +1,129 @@
+/* sha256.h - TinyCrypt interface to a SHA-256 implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to a SHA-256 implementation.
+ *
+ *  Overview:   SHA-256 is a NIST approved cryptographic hashing algorithm
+ *              specified in FIPS 180. A hash algorithm maps data of arbitrary
+ *              size to data of fixed length.
+ *
+ *  Security:   SHA-256 provides 128 bits of security against collision attacks
+ *              and 256 bits of security against pre-image attacks. SHA-256 does
+ *              NOT behave like a random oracle, but it can be used as one if
+ *              the string being hashed is prefix-free encoded before hashing.
+ *
+ *  Usage:      1) call tc_sha256_init to initialize a struct
+ *              tc_sha256_state_struct before hashing a new string.
+ *
+ *              2) call tc_sha256_update to hash the next string segment;
+ *              tc_sha256_update can be called as many times as needed to hash
+ *              all of the segments of a string; the order is important.
+ *
+ *              3) call tc_sha256_final to out put the digest from a hashing
+ *              operation.
+ */
+
+#ifndef __TC_SHA256_H__
+#define __TC_SHA256_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TC_SHA256_BLOCK_SIZE (64)
+#define TC_SHA256_DIGEST_SIZE (32)
+#define TC_SHA256_STATE_BLOCKS (TC_SHA256_DIGEST_SIZE/4)
+
+struct tc_sha256_state_struct {
+	unsigned int iv[TC_SHA256_STATE_BLOCKS];
+	uint64_t bits_hashed;
+	uint8_t leftover[TC_SHA256_BLOCK_SIZE];
+	size_t leftover_offset;
+};
+
+typedef struct tc_sha256_state_struct *TCSha256State_t;
+
+/**
+ *  @brief SHA256 initialization procedure
+ *  Initializes s
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if s == NULL
+ *  @param s Sha256 state struct
+ */
+int tc_sha256_init(TCSha256State_t s);
+
+/**
+ *  @brief SHA256 update procedure
+ *  Hashes data_length bytes addressed by data into state s
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                s == NULL,
+ *                s->iv == NULL,
+ *                data == NULL
+ *  @note Assumes s has been initialized by tc_sha256_init
+ *  @warning The state buffer 'leftover' is left in memory after processing
+ *           If your application intends to have sensitive data in this
+ *           buffer, remind to erase it after the data has been processed
+ *  @param s Sha256 state struct
+ *  @param data message to hash
+ *  @param datalen length of message to hash
+ */
+int tc_sha256_update (TCSha256State_t s, const uint8_t *data, size_t datalen);
+
+/**
+ *  @brief SHA256 final procedure
+ *  Inserts the completed hash computation into digest
+ *  @return returns TC_CRYPTO_SUCCESS (1)
+ *          returns TC_CRYPTO_FAIL (0) if:
+ *                s == NULL,
+ *                s->iv == NULL,
+ *                digest == NULL
+ *  @note Assumes: s has been initialized by tc_sha256_init
+ *        digest points to at least TC_SHA256_DIGEST_SIZE bytes
+ *  @warning The state buffer 'leftover' is left in memory after processing
+ *           If your application intends to have sensitive data in this
+ *           buffer, remind to erase it after the data has been processed
+ *  @param digest unsigned eight bit integer
+ *  @param Sha256 state struct
+ */
+int tc_sha256_final(uint8_t *digest, TCSha256State_t s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_SHA256_H__ */
diff --git a/tinycrypt/include/tinycrypt/utils.h b/tinycrypt/include/tinycrypt/utils.h
new file mode 100644
index 0000000..bab5c32
--- /dev/null
+++ b/tinycrypt/include/tinycrypt/utils.h
@@ -0,0 +1,95 @@
+/* utils.h - TinyCrypt interface to platform-dependent run-time operations */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to platform-dependent run-time operations.
+ *
+ */
+
+#ifndef __TC_UTILS_H__
+#define __TC_UTILS_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Copy the the buffer 'from' to the buffer 'to'.
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ *         returns TC_CRYPTO_FAIL (0) if:
+ *                from_len > to_len.
+ *
+ * @param to OUT -- destination buffer
+ * @param to_len IN -- length of destination buffer
+ * @param from IN -- origin buffer
+ * @param from_len IN -- length of origin buffer
+ */
+unsigned int _copy(uint8_t *to, unsigned int to_len,
+	           const uint8_t *from, unsigned int from_len);
+
+/**
+ * @brief Set the value 'val' into the buffer 'to', 'len' times.
+ *
+ * @param to OUT -- destination buffer
+ * @param val IN -- value to be set in 'to'
+ * @param len IN -- number of times the value will be copied
+ */
+void _set(void *to, uint8_t val, unsigned int len);
+
+/*
+ * @brief AES specific doubling function, which utilizes
+ * the finite field used by AES.
+ * @return Returns a^2
+ *
+ * @param a IN/OUT -- value to be doubled
+ */
+uint8_t _double_byte(uint8_t a);
+
+/*
+ * @brief Constant-time algorithm to compare if two sequences of bytes are equal
+ * @return Returns 0 if equal, and non-zero otherwise
+ *
+ * @param a IN -- sequence of bytes a
+ * @param b IN -- sequence of bytes b
+ * @param size IN -- size of sequences a and b
+ */
+int _compare(const uint8_t *a, const uint8_t *b, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_UTILS_H__ */
diff --git a/tinycrypt/src/aes_decrypt.c b/tinycrypt/src/aes_decrypt.c
new file mode 100644
index 0000000..993a618
--- /dev/null
+++ b/tinycrypt/src/aes_decrypt.c
@@ -0,0 +1,164 @@
+/* aes_decrypt.c - TinyCrypt implementation of AES decryption procedure */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/aes.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+static const uint8_t inv_sbox[256] = {
+	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
+	0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
+	0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
+	0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+	0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
+	0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
+	0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
+	0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+	0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
+	0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
+	0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
+	0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+	0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
+	0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
+	0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
+	0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+	0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
+	0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
+	0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
+	0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+	0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
+	0x55, 0x21, 0x0c, 0x7d
+};
+
+int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k)
+{
+	return tc_aes128_set_encrypt_key(s, k);
+}
+
+#define mult8(a)(_double_byte(_double_byte(_double_byte(a))))
+#define mult9(a)(mult8(a)^(a))
+#define multb(a)(mult8(a)^_double_byte(a)^(a))
+#define multd(a)(mult8(a)^_double_byte(_double_byte(a))^(a))
+#define multe(a)(mult8(a)^_double_byte(_double_byte(a))^_double_byte(a))
+
+static inline void mult_row_column(uint8_t *out, const uint8_t *in)
+{
+	out[0] = multe(in[0]) ^ multb(in[1]) ^ multd(in[2]) ^ mult9(in[3]);
+	out[1] = mult9(in[0]) ^ multe(in[1]) ^ multb(in[2]) ^ multd(in[3]);
+	out[2] = multd(in[0]) ^ mult9(in[1]) ^ multe(in[2]) ^ multb(in[3]);
+	out[3] = multb(in[0]) ^ multd(in[1]) ^ mult9(in[2]) ^ multe(in[3]);
+}
+
+static inline void inv_mix_columns(uint8_t *s)
+{
+	uint8_t t[Nb*Nk];
+
+	mult_row_column(t, s);
+	mult_row_column(&t[Nb], s+Nb);
+	mult_row_column(&t[2*Nb], s+(2*Nb));
+	mult_row_column(&t[3*Nb], s+(3*Nb));
+	(void)_copy(s, sizeof(t), t, sizeof(t));
+}
+
+static inline void add_round_key(uint8_t *s, const unsigned int *k)
+{
+	s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16);
+	s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]);
+	s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16);
+	s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]);
+	s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16);
+	s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]);
+	s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16);
+	s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]);
+}
+
+static inline void inv_sub_bytes(uint8_t *s)
+{
+	unsigned int i;
+
+	for (i = 0; i < (Nb*Nk); ++i) {
+		s[i] = inv_sbox[s[i]];
+	}
+}
+
+/*
+ * This inv_shift_rows also implements the matrix flip required for
+ * inv_mix_columns, but performs it here to reduce the number of memory
+ * operations.
+ */
+static inline void inv_shift_rows(uint8_t *s)
+{
+	uint8_t t[Nb*Nk];
+
+	t[0]  = s[0]; t[1] = s[13]; t[2] = s[10]; t[3] = s[7];
+	t[4]  = s[4]; t[5] = s[1]; t[6] = s[14]; t[7] = s[11];
+	t[8]  = s[8]; t[9] = s[5]; t[10] = s[2]; t[11] = s[15];
+	t[12] = s[12]; t[13] = s[9]; t[14] = s[6]; t[15] = s[3];
+	(void)_copy(s, sizeof(t), t, sizeof(t));
+}
+
+int tc_aes_decrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
+{
+	uint8_t state[Nk*Nb];
+	unsigned int i;
+
+	if (out == (uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (in == (const uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (s == (TCAesKeySched_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	(void)_copy(state, sizeof(state), in, sizeof(state));
+
+	add_round_key(state, s->words + Nb*Nr);
+
+	for (i = Nr - 1; i > 0; --i) {
+		inv_shift_rows(state);
+		inv_sub_bytes(state);
+		add_round_key(state, s->words + Nb*i);
+		inv_mix_columns(state);
+	}
+
+	inv_shift_rows(state);
+	inv_sub_bytes(state);
+	add_round_key(state, s->words);
+
+	(void)_copy(out, sizeof(state), state, sizeof(state));
+
+	/*zeroing out the state buffer */
+	_set(state, TC_ZERO_BYTE, sizeof(state));
+
+
+	return TC_CRYPTO_SUCCESS;
+}
diff --git a/tinycrypt/src/aes_encrypt.c b/tinycrypt/src/aes_encrypt.c
new file mode 100644
index 0000000..8991aee
--- /dev/null
+++ b/tinycrypt/src/aes_encrypt.c
@@ -0,0 +1,191 @@
+/* aes_encrypt.c - TinyCrypt implementation of AES encryption procedure */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/aes.h>
+#include <tinycrypt/utils.h>
+#include <tinycrypt/constants.h>
+
+static const uint8_t sbox[256] = {
+	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
+	0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+	0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
+	0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
+	0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+	0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
+	0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
+	0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+	0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
+	0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
+	0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+	0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
+	0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
+	0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+	0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
+	0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
+	0xb0, 0x54, 0xbb, 0x16
+};
+
+static inline unsigned int rotword(unsigned int a)
+{
+	return (((a) >> 24)|((a) << 8));
+}
+
+#define subbyte(a, o)(sbox[((a) >> (o))&0xff] << (o))
+#define subword(a)(subbyte(a, 24)|subbyte(a, 16)|subbyte(a, 8)|subbyte(a, 0))
+
+int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k)
+{
+	const unsigned int rconst[11] = {
+		0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
+		0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000
+	};
+	unsigned int i;
+	unsigned int t;
+
+	if (s == (TCAesKeySched_t) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (k == (const uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	for (i = 0; i < Nk; ++i) {
+		s->words[i] = (k[Nb*i]<<24) | (k[Nb*i+1]<<16) |
+			      (k[Nb*i+2]<<8) | (k[Nb*i+3]);
+	}
+
+	for (; i < (Nb * (Nr + 1)); ++i) {
+		t = s->words[i-1];
+		if ((i % Nk) == 0) {
+			t = subword(rotword(t)) ^ rconst[i/Nk];
+		}
+		s->words[i] = s->words[i-Nk] ^ t;
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+static inline void add_round_key(uint8_t *s, const unsigned int *k)
+{
+	s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16);
+	s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]);
+	s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16);
+	s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]);
+	s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16);
+	s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]);
+	s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16);
+	s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]);
+}
+
+static inline void sub_bytes(uint8_t *s)
+{
+	unsigned int i;
+
+	for (i = 0; i < (Nb * Nk); ++i) {
+		s[i] = sbox[s[i]];
+	}
+}
+
+#define triple(a)(_double_byte(a)^(a))
+
+static inline void mult_row_column(uint8_t *out, const uint8_t *in)
+{
+	out[0] = _double_byte(in[0]) ^ triple(in[1]) ^ in[2] ^ in[3];
+	out[1] = in[0] ^ _double_byte(in[1]) ^ triple(in[2]) ^ in[3];
+	out[2] = in[0] ^ in[1] ^ _double_byte(in[2]) ^ triple(in[3]);
+	out[3] = triple(in[0]) ^ in[1] ^ in[2] ^ _double_byte(in[3]);
+}
+
+static inline void mix_columns(uint8_t *s)
+{
+	uint8_t t[Nb*Nk];
+
+	mult_row_column(t, s);
+	mult_row_column(&t[Nb], s+Nb);
+	mult_row_column(&t[2 * Nb], s + (2 * Nb));
+	mult_row_column(&t[3 * Nb], s + (3 * Nb));
+	(void) _copy(s, sizeof(t), t, sizeof(t));
+}
+
+/*
+ * This shift_rows also implements the matrix flip required for mix_columns, but
+ * performs it here to reduce the number of memory operations.
+ */
+static inline void shift_rows(uint8_t *s)
+{
+	uint8_t t[Nb * Nk];
+
+	t[0]  = s[0]; t[1] = s[5]; t[2] = s[10]; t[3] = s[15];
+	t[4]  = s[4]; t[5] = s[9]; t[6] = s[14]; t[7] = s[3];
+	t[8]  = s[8]; t[9] = s[13]; t[10] = s[2]; t[11] = s[7];
+	t[12] = s[12]; t[13] = s[1]; t[14] = s[6]; t[15] = s[11];
+	(void) _copy(s, sizeof(t), t, sizeof(t));
+}
+
+int tc_aes_encrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
+{
+	uint8_t state[Nk*Nb];
+	unsigned int i;
+
+	if (out == (uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (in == (const uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (s == (TCAesKeySched_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	(void)_copy(state, sizeof(state), in, sizeof(state));
+	add_round_key(state, s->words);
+
+	for (i = 0; i < (Nr - 1); ++i) {
+		sub_bytes(state);
+		shift_rows(state);
+		mix_columns(state);
+		add_round_key(state, s->words + Nb*(i+1));
+	}
+
+	sub_bytes(state);
+	shift_rows(state);
+	add_round_key(state, s->words + Nb*(i+1));
+
+	(void)_copy(out, sizeof(state), state, sizeof(state));
+
+	/* zeroing out the state buffer */
+	_set(state, TC_ZERO_BYTE, sizeof(state));
+
+	return TC_CRYPTO_SUCCESS;
+}
diff --git a/tinycrypt/src/cbc_mode.c b/tinycrypt/src/cbc_mode.c
new file mode 100644
index 0000000..62d7879
--- /dev/null
+++ b/tinycrypt/src/cbc_mode.c
@@ -0,0 +1,114 @@
+/* cbc_mode.c - TinyCrypt implementation of CBC mode encryption & decryption */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/cbc_mode.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
+			    unsigned int inlen, const uint8_t *iv,
+			    const TCAesKeySched_t sched)
+{
+
+	uint8_t buffer[TC_AES_BLOCK_SIZE];
+	unsigned int n, m;
+
+	/* input sanity check: */
+	if (out == (uint8_t *) 0 ||
+	    in == (const uint8_t *) 0 ||
+	    sched == (TCAesKeySched_t) 0 ||
+	    inlen == 0 ||
+	    outlen == 0 ||
+	    (inlen % TC_AES_BLOCK_SIZE) != 0 ||
+	    (outlen % TC_AES_BLOCK_SIZE) != 0 ||
+	    outlen != inlen + TC_AES_BLOCK_SIZE) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* copy iv to the buffer */
+	(void)_copy(buffer, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
+	/* copy iv to the output buffer */
+	(void)_copy(out, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
+	out += TC_AES_BLOCK_SIZE;
+
+	for (n = m = 0; n < inlen; ++n) {
+		buffer[m++] ^= *in++;
+		if (m == TC_AES_BLOCK_SIZE) {
+			(void)tc_aes_encrypt(buffer, buffer, sched);
+			(void)_copy(out, TC_AES_BLOCK_SIZE,
+				    buffer, TC_AES_BLOCK_SIZE);
+			out += TC_AES_BLOCK_SIZE;
+			m = 0;
+		}
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
+			    unsigned int inlen, const uint8_t *iv,
+			    const TCAesKeySched_t sched)
+{
+
+	uint8_t buffer[TC_AES_BLOCK_SIZE];
+	const uint8_t *p;
+	unsigned int n, m;
+
+	/* sanity check the inputs */
+	if (out == (uint8_t *) 0 ||
+	    in == (const uint8_t *) 0 ||
+	    sched == (TCAesKeySched_t) 0 ||
+	    inlen == 0 ||
+	    outlen == 0 ||
+	    (inlen % TC_AES_BLOCK_SIZE) != 0 ||
+	    (outlen % TC_AES_BLOCK_SIZE) != 0 ||
+	    outlen != inlen - TC_AES_BLOCK_SIZE) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/*
+	 * Note that in == iv + ciphertext, i.e. the iv and the ciphertext are
+	 * contiguous. This allows for a very efficient decryption algorithm
+	 * that would not otherwise be possible.
+	 */
+	p = iv;
+	for (n = m = 0; n < inlen; ++n) {
+		if ((n % TC_AES_BLOCK_SIZE) == 0) {
+			(void)tc_aes_decrypt(buffer, in, sched);
+			in += TC_AES_BLOCK_SIZE;
+			m = 0;
+		}
+		*out++ = buffer[m++] ^ *p++;
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
diff --git a/tinycrypt/src/ccm_mode.c b/tinycrypt/src/ccm_mode.c
new file mode 100644
index 0000000..929adac
--- /dev/null
+++ b/tinycrypt/src/ccm_mode.c
@@ -0,0 +1,266 @@
+/* ccm_mode.c - TinyCrypt implementation of CCM mode */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/ccm_mode.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+#include <stdio.h>
+
+int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
+		  unsigned int nlen, unsigned int mlen)
+{
+
+	/* input sanity check: */
+	if (c == (TCCcmMode_t) 0 ||
+	    sched == (TCAesKeySched_t) 0 ||
+	    nonce == (uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (nlen != 13) {
+		return TC_CRYPTO_FAIL; /* The allowed nonce size is: 13. See documentation.*/
+	} else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) {
+		return TC_CRYPTO_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/
+	}
+
+	c->mlen = mlen;
+	c->sched = sched;
+	c->nonce = nonce;
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+/**
+ * Variation of CBC-MAC mode used in CCM.
+ */
+static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, unsigned int dlen,
+			unsigned int flag, TCAesKeySched_t sched)
+{
+
+	unsigned int i;
+
+	if (flag > 0) {
+		T[0] ^= (uint8_t)(dlen >> 8);
+		T[1] ^= (uint8_t)(dlen);
+		dlen += 2; i = 2;
+	} else {
+		i = 0;
+	}
+
+	while (i < dlen) {
+		T[i++ % (Nb * Nk)] ^= *data++;
+		if (((i % (Nb * Nk)) == 0) || dlen == i) {
+			(void) tc_aes_encrypt(T, T, sched);
+		}
+	}
+}
+
+/**
+ * Variation of CTR mode used in CCM.
+ * The CTR mode used by CCM is slightly different than the conventional CTR
+ * mode (the counter is increased before encryption, instead of after
+ * encryption). Besides, it is assumed that the counter is stored in the last
+ * 2 bytes of the nonce.
+ */
+static int ccm_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
+			unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
+{
+
+	uint8_t buffer[TC_AES_BLOCK_SIZE];
+	uint8_t nonce[TC_AES_BLOCK_SIZE];
+	uint16_t block_num;
+	unsigned int i;
+
+	/* input sanity check: */
+	if (out == (uint8_t *) 0 ||
+	    in == (uint8_t *) 0 ||
+	    ctr == (uint8_t *) 0 ||
+	    sched == (TCAesKeySched_t) 0 ||
+	    inlen == 0 ||
+	    outlen == 0 ||
+	    outlen != inlen) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* copy the counter to the nonce */
+	(void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
+
+	/* select the last 2 bytes of the nonce to be incremented */
+	block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15]));
+	for (i = 0; i < inlen; ++i) {
+		if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
+			block_num++;
+			nonce[14] = (uint8_t)(block_num >> 8);
+			nonce[15] = (uint8_t)(block_num);
+			if (!tc_aes_encrypt(buffer, nonce, sched)) {
+				return TC_CRYPTO_FAIL;
+			}
+		}
+		/* update the output */
+		*out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++;
+	}
+
+	/* update the counter */
+	ctr[14] = nonce[14]; ctr[15] = nonce[15];
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
+				 const uint8_t *associated_data,
+				 unsigned int alen, const uint8_t *payload,
+				 unsigned int plen, TCCcmMode_t c)
+{
+
+	/* input sanity check: */
+	if ((out == (uint8_t *) 0) ||
+		(c == (TCCcmMode_t) 0) ||
+		((plen > 0) && (payload == (uint8_t *) 0)) ||
+		((alen > 0) && (associated_data == (uint8_t *) 0)) ||
+		(alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
+		(plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
+		(olen < (plen + c->mlen))) {  /* invalid output buffer size */
+		return TC_CRYPTO_FAIL;
+	}
+
+	uint8_t b[Nb * Nk];
+	uint8_t tag[Nb * Nk];
+	unsigned int i;
+
+	/* GENERATING THE AUTHENTICATION TAG: */
+
+	/* formatting the sequence b for authentication: */
+	b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1);
+	for (i = 1; i <= 13; ++i) {
+		b[i] = c->nonce[i - 1];
+	}
+	b[14] = (uint8_t)(plen >> 8);
+	b[15] = (uint8_t)(plen);
+
+	/* computing the authentication tag using cbc-mac: */
+	(void) tc_aes_encrypt(tag, b, c->sched);
+	if (alen > 0) {
+		ccm_cbc_mac(tag, associated_data, alen, 1, c->sched);
+	}
+	if (plen > 0) {
+		ccm_cbc_mac(tag, payload, plen, 0, c->sched);
+	}
+
+	/* ENCRYPTION: */
+
+	/* formatting the sequence b for encryption: */
+	b[0] = 1; /* q - 1 = 2 - 1 = 1 */
+	b[14] = b[15] = TC_ZERO_BYTE;
+
+	/* encrypting payload using ctr mode: */
+	ccm_ctr_mode(out, plen, payload, plen, b, c->sched);
+
+	b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter for ctr_mode (0):*/
+
+	/* encrypting b and adding the tag to the output: */
+	(void) tc_aes_encrypt(b, b, c->sched);
+	out += plen;
+	for (i = 0; i < c->mlen; ++i) {
+		*out++ = tag[i] ^ b[i];
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
+				   const uint8_t *associated_data,
+				   unsigned int alen, const uint8_t *payload,
+				   unsigned int plen, TCCcmMode_t c)
+{
+
+	/* input sanity check: */
+	if ((out == (uint8_t *) 0) ||
+	    (c == (TCCcmMode_t) 0) ||
+	    ((plen > 0) && (payload == (uint8_t *) 0)) ||
+	    ((alen > 0) && (associated_data == (uint8_t *) 0)) ||
+	    (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
+	    (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
+	    (olen < plen - c->mlen)) { /* invalid output buffer size */
+		return TC_CRYPTO_FAIL;
+  }
+
+	uint8_t b[Nb * Nk];
+	uint8_t tag[Nb * Nk];
+	unsigned int i;
+
+	/* DECRYPTION: */
+
+	/* formatting the sequence b for decryption: */
+	b[0] = 1; /* q - 1 = 2 - 1 = 1 */
+	for (i = 1; i < 14; ++i) {
+		b[i] = c->nonce[i - 1];
+	}
+	b[14] = b[15] = TC_ZERO_BYTE; /* initial counter value is 0 */
+
+	/* decrypting payload using ctr mode: */
+	ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched);
+
+	b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter value (0) */
+
+	/* encrypting b and restoring the tag from input: */
+	(void) tc_aes_encrypt(b, b, c->sched);
+	for (i = 0; i < c->mlen; ++i) {
+		tag[i] = *(payload + plen - c->mlen + i) ^ b[i];
+	}
+
+	/* VERIFYING THE AUTHENTICATION TAG: */
+
+	/* formatting the sequence b for authentication: */
+	b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1);
+	for (i = 1; i < 14; ++i) {
+		b[i] = c->nonce[i - 1];
+	}
+	b[14] = (uint8_t)((plen - c->mlen) >> 8);
+	b[15] = (uint8_t)(plen - c->mlen);
+
+	/* computing the authentication tag using cbc-mac: */
+	(void) tc_aes_encrypt(b, b, c->sched);
+	if (alen > 0) {
+		ccm_cbc_mac(b, associated_data, alen, 1, c->sched);
+	}
+	if (plen > 0) {
+		ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched);
+	}
+
+	/* comparing the received tag and the computed one: */
+	if (_compare(b, tag, c->mlen) == 0) {
+		return TC_CRYPTO_SUCCESS;
+  	} else {
+		/* erase the decrypted buffer in case of mac validation failure: */
+		_set(out, 0, plen - c->mlen);
+		return TC_CRYPTO_FAIL;
+	}
+}
diff --git a/tinycrypt/src/cmac_mode.c b/tinycrypt/src/cmac_mode.c
new file mode 100644
index 0000000..96d147e
--- /dev/null
+++ b/tinycrypt/src/cmac_mode.c
@@ -0,0 +1,254 @@
+/* cmac_mode.c - TinyCrypt CMAC mode implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/aes.h>
+#include <tinycrypt/cmac_mode.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+/* max number of calls until change the key (2^48).*/
+const static uint64_t MAX_CALLS = ((uint64_t)1 << 48);
+
+/*
+ *  gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte
+ *  array with byte 0 the most significant and byte 15 the least significant.
+ *  High bit carry reduction is based on the primitive polynomial
+ *
+ *                     X^128 + X^7 + X^2 + X + 1,
+ *
+ *  which leads to the reduction formula X^128 = X^7 + X^2 + X + 1. Indeed,
+ *  since 0 = (X^128 + X^7 + X^2 + 1) mod (X^128 + X^7 + X^2 + X + 1) and since
+ *  addition of polynomials with coefficients in Z/Z(2) is just XOR, we can
+ *  add X^128 to both sides to get
+ *
+ *       X^128 = (X^7 + X^2 + X + 1) mod (X^128 + X^7 + X^2 + X + 1)
+ *
+ *  and the coefficients of the polynomial on the right hand side form the
+ *  string 1000 0111 = 0x87, which is the value of gf_wrap.
+ *
+ *  This gets used in the following way. Doubling in GF(2^128) is just a left
+ *  shift by 1 bit, except when the most significant bit is 1. In the latter
+ *  case, the relation X^128 = X^7 + X^2 + X + 1 says that the high order bit
+ *  that overflows beyond 128 bits can be replaced by addition of
+ *  X^7 + X^2 + X + 1 <--> 0x87 to the low order 128 bits. Since addition
+ *  in GF(2^128) is represented by XOR, we therefore only have to XOR 0x87
+ *  into the low order byte after a left shift when the starting high order
+ *  bit is 1.
+ */
+const unsigned char gf_wrap = 0x87;
+
+/*
+ *  assumes: out != NULL and points to a GF(2^n) value to receive the
+ *            doubled value;
+ *           in != NULL and points to a 16 byte GF(2^n) value
+ *            to double;
+ *           the in and out buffers do not overlap.
+ *  effects: doubles the GF(2^n) value pointed to by "in" and places
+ *           the result in the GF(2^n) value pointed to by "out."
+ */
+void gf_double(uint8_t *out, uint8_t *in)
+{
+
+	/* start with low order byte */
+	uint8_t *x = in + (TC_AES_BLOCK_SIZE - 1);
+
+	/* if msb == 1, we need to add the gf_wrap value, otherwise add 0 */
+	uint8_t carry = (in[0] >> 7) ? gf_wrap : 0;
+
+	out += (TC_AES_BLOCK_SIZE - 1);
+	for (;;) {
+		*out-- = (*x << 1) ^ carry;
+		if (x == in) {
+			break;
+		}
+		carry = *x-- >> 7;
+	}
+}
+
+int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, TCAesKeySched_t sched)
+{
+
+	/* input sanity check: */
+	if (s == (TCCmacState_t) 0 ||
+	    key == (const uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* put s into a known state */
+	_set(s, 0, sizeof(*s));
+	s->sched = sched;
+
+	/* configure the encryption key used by the underlying block cipher */
+	tc_aes128_set_encrypt_key(s->sched, key);
+
+	/* compute s->K1 and s->K2 from s->iv using s->keyid */
+	_set(s->iv, 0, TC_AES_BLOCK_SIZE);
+	tc_aes_encrypt(s->iv, s->iv, s->sched);
+	gf_double (s->K1, s->iv);
+	gf_double (s->K2, s->K1);
+
+	/* reset s->iv to 0 in case someone wants to compute now */
+	tc_cmac_init(s);
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cmac_erase(TCCmacState_t s)
+{
+	if (s == (TCCmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* destroy the current state */
+	_set(s, 0, sizeof(*s));
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cmac_init(TCCmacState_t s)
+{
+	/* input sanity check: */
+	if (s == (TCCmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* CMAC starts with an all zero initialization vector */
+	_set(s->iv, 0, TC_AES_BLOCK_SIZE);
+
+	/* and the leftover buffer is empty */
+	_set(s->leftover, 0, TC_AES_BLOCK_SIZE);
+	s->leftover_offset = 0;
+
+	/* Set countdown to max number of calls allowed before re-keying: */
+	s->countdown = MAX_CALLS;
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length)
+{
+	unsigned int i;
+
+	/* input sanity check: */
+	if (s == (TCCmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+	if (data_length == 0) {
+		return  TC_CRYPTO_SUCCESS;
+	}
+	if (data == (const uint8_t *) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	if (s->countdown == 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	s->countdown--;
+
+	if (s->leftover_offset > 0) {
+		/* last data added to s didn't end on a TC_AES_BLOCK_SIZE byte boundary */
+		size_t remaining_space = TC_AES_BLOCK_SIZE - s->leftover_offset;
+
+		if (data_length < remaining_space) {
+			/* still not enough data to encrypt this time either */
+			_copy(&s->leftover[s->leftover_offset], data_length, data, data_length);
+			s->leftover_offset += data_length;
+			return TC_CRYPTO_SUCCESS;
+		}
+		/* leftover block is now full; encrypt it first */
+		_copy(&s->leftover[s->leftover_offset],
+		      remaining_space,
+		      data,
+		      remaining_space);
+		data_length -= remaining_space;
+		data += remaining_space;
+		s->leftover_offset = 0;
+
+		for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
+			s->iv[i] ^= s->leftover[i];
+		}
+		tc_aes_encrypt(s->iv, s->iv, s->sched);
+	}
+
+	/* CBC encrypt each (except the last) of the data blocks */
+	while (data_length > TC_AES_BLOCK_SIZE) {
+		for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
+			s->iv[i] ^= data[i];
+		}
+		tc_aes_encrypt(s->iv, s->iv, s->sched);
+		data += TC_AES_BLOCK_SIZE;
+		data_length  -= TC_AES_BLOCK_SIZE;
+	}
+
+	if (data_length > 0) {
+		/* save leftover data for next time */
+		_copy(s->leftover, data_length, data, data_length);
+		s->leftover_offset = data_length;
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cmac_final(uint8_t *tag, TCCmacState_t s)
+{
+	uint8_t *k;
+	unsigned int i;
+
+	/* input sanity check: */
+	if (tag == (uint8_t *) 0 ||
+	    s == (TCCmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	if (s->leftover_offset == TC_AES_BLOCK_SIZE) {
+		/* the last message block is a full-sized block */
+		k = (uint8_t *) s->K1;
+	} else {
+		/* the final message block is not a full-sized  block */
+		size_t remaining = TC_AES_BLOCK_SIZE - s->leftover_offset;
+
+		_set(&s->leftover[s->leftover_offset], 0, remaining);
+		s->leftover[s->leftover_offset] = TC_CMAC_PADDING;
+		k = (uint8_t *) s->K2;
+	}
+	for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
+		s->iv[i] ^= s->leftover[i] ^ k[i];
+	}
+
+	tc_aes_encrypt(tag, s->iv, s->sched);
+
+	/* erasing state: */
+	tc_cmac_erase(s);
+
+	return TC_CRYPTO_SUCCESS;
+}
diff --git a/tinycrypt/src/ctr_mode.c b/tinycrypt/src/ctr_mode.c
new file mode 100644
index 0000000..1dfb92d
--- /dev/null
+++ b/tinycrypt/src/ctr_mode.c
@@ -0,0 +1,85 @@
+/* ctr_mode.c - TinyCrypt CTR mode implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/constants.h>
+#include <tinycrypt/ctr_mode.h>
+#include <tinycrypt/utils.h>
+
+int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
+		unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
+{
+
+	uint8_t buffer[TC_AES_BLOCK_SIZE];
+	uint8_t nonce[TC_AES_BLOCK_SIZE];
+	unsigned int block_num;
+	unsigned int i;
+
+	/* input sanity check: */
+	if (out == (uint8_t *) 0 ||
+	    in == (uint8_t *) 0 ||
+	    ctr == (uint8_t *) 0 ||
+	    sched == (TCAesKeySched_t) 0 ||
+	    inlen == 0 ||
+	    outlen == 0 ||
+	    outlen != inlen) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* copy the ctr to the nonce */
+	(void)_copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
+
+	/* select the last 4 bytes of the nonce to be incremented */
+	block_num = (nonce[12] << 24) | (nonce[13] << 16) |
+		    (nonce[14] << 8) | (nonce[15]);
+	for (i = 0; i < inlen; ++i) {
+		if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
+			/* encrypt data using the current nonce */
+			if (tc_aes_encrypt(buffer, nonce, sched)) {
+				block_num++;
+				nonce[12] = (uint8_t)(block_num >> 24);
+				nonce[13] = (uint8_t)(block_num >> 16);
+				nonce[14] = (uint8_t)(block_num >> 8);
+				nonce[15] = (uint8_t)(block_num);
+			} else {
+				return TC_CRYPTO_FAIL;
+			}
+		}
+		/* update the output */
+		*out++ = buffer[i%(TC_AES_BLOCK_SIZE)] ^ *in++;
+	}
+
+	/* update the counter */
+	ctr[12] = nonce[12]; ctr[13] = nonce[13];
+	ctr[14] = nonce[14]; ctr[15] = nonce[15];
+
+	return TC_CRYPTO_SUCCESS;
+}
diff --git a/tinycrypt/src/ctr_prng.c b/tinycrypt/src/ctr_prng.c
new file mode 100644
index 0000000..cac2cc4
--- /dev/null
+++ b/tinycrypt/src/ctr_prng.c
@@ -0,0 +1,283 @@
+/* ctr_prng.c - TinyCrypt implementation of CTR-PRNG */
+
+/*
+ * Copyright (c) 2016, Chris Morrison
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/ctr_prng.h>
+#include <tinycrypt/utils.h>
+#include <tinycrypt/constants.h>
+#include <string.h>
+
+/*
+ * This PRNG is based on the CTR_DRBG described in Recommendation for Random
+ * Number Generation Using Deterministic Random Bit Generators,
+ * NIST SP 800-90A Rev. 1.
+ *
+ * Annotations to particular steps (e.g. 10.2.1.2 Step 1) refer to the steps
+ * described in that document.
+ *
+ */
+
+/**
+ *  @brief Array incrementer
+ *  Treats the supplied array as one contiguous number (MSB in arr[0]), and
+ *  increments it by one
+ *  @return none
+ *  @param arr IN/OUT -- array to be incremented
+ *  @param len IN -- size of arr in bytes
+ */
+static void arrInc(uint8_t arr[], unsigned int len)
+{
+	unsigned int i;
+	if (0 != arr) {
+		for (i = len; i > 0U; i--) {
+			if (++arr[i-1] != 0U) {
+				break;
+			}
+		}
+	}
+}
+
+/**
+ *  @brief CTR PRNG update
+ *  Updates the internal state of supplied the CTR PRNG context
+ *  increments it by one
+ *  @return none
+ *  @note Assumes: providedData is (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes long
+ *  @param ctx IN/OUT -- CTR PRNG state
+ *  @param providedData IN -- data used when updating the internal state
+ */
+static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const * const providedData)
+{
+	if (0 != ctx) {
+		/* 10.2.1.2 step 1 */
+		uint8_t temp[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
+		unsigned int len = 0U;
+
+		/* 10.2.1.2 step 2 */
+		while (len < sizeof temp) {
+			unsigned int blocklen = sizeof(temp) - len;
+			uint8_t output_block[TC_AES_BLOCK_SIZE];
+
+			/* 10.2.1.2 step 2.1 */
+			arrInc(ctx->V, sizeof ctx->V);
+
+			/* 10.2.1.2 step 2.2 */
+			if (blocklen > TC_AES_BLOCK_SIZE) {
+				blocklen = TC_AES_BLOCK_SIZE;
+			}
+			(void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
+
+			/* 10.2.1.2 step 2.3/step 3 */
+			memcpy(&(temp[len]), output_block, blocklen);
+
+			len += blocklen;
+		}
+
+		/* 10.2.1.2 step 4 */
+		if (0 != providedData) {
+			unsigned int i;
+			for (i = 0U; i < sizeof temp; i++) {
+				temp[i] ^= providedData[i];
+			}
+		}
+
+		/* 10.2.1.2 step 5 */
+		(void)tc_aes128_set_encrypt_key(&ctx->key, temp);
+    
+		/* 10.2.1.2 step 6 */
+		memcpy(ctx->V, &(temp[TC_AES_KEY_SIZE]), TC_AES_BLOCK_SIZE);
+	}
+}
+
+int tc_ctr_prng_init(TCCtrPrng_t * const ctx, 
+		     uint8_t const * const entropy,
+		     unsigned int entropyLen, 
+		     uint8_t const * const personalization,
+		     unsigned int pLen)
+{
+	int result = TC_CRYPTO_FAIL;	
+	unsigned int i;
+	uint8_t personalization_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
+	uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
+	uint8_t zeroArr[TC_AES_BLOCK_SIZE] = {0U};
+  
+	if (0 != personalization) {
+		/* 10.2.1.3.1 step 1 */
+		unsigned int len = pLen;
+		if (len > sizeof personalization_buf) {
+			len = sizeof personalization_buf;
+		}
+
+		/* 10.2.1.3.1 step 2 */
+		memcpy(personalization_buf, personalization, len);
+	}
+
+	if ((0 != ctx) && (0 != entropy) && (entropyLen >= sizeof seed_material)) {
+		/* 10.2.1.3.1 step 3 */
+		memcpy(seed_material, entropy, sizeof seed_material);
+		for (i = 0U; i < sizeof seed_material; i++) {
+			seed_material[i] ^= personalization_buf[i];
+		}
+
+		/* 10.2.1.3.1 step 4 */
+		(void)tc_aes128_set_encrypt_key(&ctx->key, zeroArr);
+
+		/* 10.2.1.3.1 step 5 */
+		memset(ctx->V,   0x00, sizeof ctx->V);
+    
+		/* 10.2.1.3.1 step 6 */    
+		tc_ctr_prng_update(ctx, seed_material);
+
+		/* 10.2.1.3.1 step 7 */
+		ctx->reseedCount = 1U;
+
+		result = TC_CRYPTO_SUCCESS;
+	}
+	return result;
+}
+
+int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx, 
+			uint8_t const * const entropy,
+			unsigned int entropyLen,
+			uint8_t const * const additional_input,
+			unsigned int additionallen)
+{
+	unsigned int i;
+	int result = TC_CRYPTO_FAIL;
+	uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
+	uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
+
+	if (0 != additional_input) {
+		/* 10.2.1.4.1 step 1 */
+		unsigned int len = additionallen;
+		if (len > sizeof additional_input_buf) {
+			len = sizeof additional_input_buf;
+		}
+
+		/* 10.2.1.4.1 step 2 */
+		memcpy(additional_input_buf, additional_input, len);
+	}
+	
+	unsigned int seedlen = (unsigned int)TC_AES_KEY_SIZE + (unsigned int)TC_AES_BLOCK_SIZE;
+	if ((0 != ctx) && (entropyLen >= seedlen)) {
+		/* 10.2.1.4.1 step 3 */
+		memcpy(seed_material, entropy, sizeof seed_material);
+		for (i = 0U; i < sizeof seed_material; i++) {
+			seed_material[i] ^= additional_input_buf[i];
+		}
+
+		/* 10.2.1.4.1 step 4 */
+		tc_ctr_prng_update(ctx, seed_material);
+
+		/* 10.2.1.4.1 step 5 */
+		ctx->reseedCount = 1U;
+
+		result = TC_CRYPTO_SUCCESS;
+	}
+	return result;
+}
+
+int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
+			uint8_t const * const additional_input,
+			unsigned int additionallen,
+			uint8_t * const out,
+			unsigned int outlen)
+{
+	/* 2^48 - see section 10.2.1 */
+	static const uint64_t MAX_REQS_BEFORE_RESEED = 0x1000000000000ULL; 
+
+	/* 2^19 bits - see section 10.2.1 */ 
+	static const unsigned int MAX_BYTES_PER_REQ = 65536U; 
+
+	unsigned int result = TC_CRYPTO_FAIL;
+
+	if ((0 != ctx) && (0 != out) && (outlen < MAX_BYTES_PER_REQ)) {
+		/* 10.2.1.5.1 step 1 */
+		if (ctx->reseedCount > MAX_REQS_BEFORE_RESEED) {
+			result = TC_CTR_PRNG_RESEED_REQ;
+		} else {
+			uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
+			if (0 != additional_input) {
+				/* 10.2.1.5.1 step 2  */
+				unsigned int len = additionallen;
+				if (len > sizeof additional_input_buf) {
+					len = sizeof additional_input_buf;
+				}
+				memcpy(additional_input_buf, additional_input, len);
+				tc_ctr_prng_update(ctx, additional_input_buf);
+			}
+      
+			/* 10.2.1.5.1 step 3 - implicit */
+
+			/* 10.2.1.5.1 step 4 */
+			unsigned int len = 0U;      
+			while (len < outlen) {
+				unsigned int blocklen = outlen - len;
+				uint8_t output_block[TC_AES_BLOCK_SIZE];
+
+				/* 10.2.1.5.1 step 4.1 */
+				arrInc(ctx->V, sizeof ctx->V);
+
+				/* 10.2.1.5.1 step 4.2 */
+				(void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
+      
+				/* 10.2.1.5.1 step 4.3/step 5 */
+				if (blocklen > TC_AES_BLOCK_SIZE) {
+					blocklen = TC_AES_BLOCK_SIZE;
+				}
+				memcpy(&(out[len]), output_block, blocklen);
+
+				len += blocklen;
+			}
+      
+			/* 10.2.1.5.1 step 6 */
+			tc_ctr_prng_update(ctx, additional_input_buf);
+
+			/* 10.2.1.5.1 step 7 */
+			ctx->reseedCount++;
+
+			/* 10.2.1.5.1 step 8 */
+			result = TC_CRYPTO_SUCCESS;
+		}
+	}
+
+	return result;
+}
+
+void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx)
+{
+	if (0 != ctx) {
+		memset(ctx->key.words, 0x00, sizeof ctx->key.words);
+		memset(ctx->V,         0x00, sizeof ctx->V);
+		ctx->reseedCount = 0U;
+	}
+}
+
+
+
+
diff --git a/tinycrypt/src/ecc.c b/tinycrypt/src/ecc.c
new file mode 100644
index 0000000..46080bf
--- /dev/null
+++ b/tinycrypt/src/ecc.c
@@ -0,0 +1,942 @@
+/* ecc.c - TinyCrypt implementation of common ECC functions */
+
+/*
+ * Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/ecc.h>
+#include <tinycrypt/ecc_platform_specific.h>
+#include <string.h>
+
+/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
+ * has access to enough entropy in order to feed the PRNG regularly. */
+#if default_RNG_defined
+static uECC_RNG_Function g_rng_function = &default_CSPRNG;
+#else
+static uECC_RNG_Function g_rng_function = 0;
+#endif
+
+void uECC_set_rng(uECC_RNG_Function rng_function)
+{
+	g_rng_function = rng_function;
+}
+
+uECC_RNG_Function uECC_get_rng(void)
+{
+	return g_rng_function;
+}
+
+int uECC_curve_private_key_size(uECC_Curve curve)
+{
+	return BITS_TO_BYTES(curve->num_n_bits);
+}
+
+int uECC_curve_public_key_size(uECC_Curve curve)
+{
+	return 2 * curve->num_bytes;
+}
+
+void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words)
+{
+	wordcount_t i;
+	for (i = 0; i < num_words; ++i) {
+		 vli[i] = 0;
+	}
+}
+
+uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words)
+{
+	uECC_word_t bits = 0;
+	wordcount_t i;
+	for (i = 0; i < num_words; ++i) {
+		bits |= vli[i];
+	}
+	return (bits == 0);
+}
+
+uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
+{
+	return (vli[bit >> uECC_WORD_BITS_SHIFT] &
+		((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
+}
+
+/* Counts the number of words in vli. */
+static wordcount_t vli_numDigits(const uECC_word_t *vli,
+				 const wordcount_t max_words)
+{
+
+	wordcount_t i;
+	/* Search from the end until we find a non-zero digit. We do it in reverse
+	 * because we expect that most digits will be nonzero. */
+	for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {
+	}
+
+	return (i + 1);
+}
+
+bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
+			    const wordcount_t max_words)
+{
+
+	uECC_word_t i;
+	uECC_word_t digit;
+
+	wordcount_t num_digits = vli_numDigits(vli, max_words);
+	if (num_digits == 0) {
+		return 0;
+	}
+
+	digit = vli[num_digits - 1];
+	for (i = 0; digit; ++i) {
+		digit >>= 1;
+	}
+
+	return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
+}
+
+void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
+		  wordcount_t num_words)
+{
+	wordcount_t i;
+
+	for (i = 0; i < num_words; ++i) {
+		dest[i] = src[i];
+  	}
+}
+
+cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
+				const uECC_word_t *right,
+				wordcount_t num_words)
+{
+	wordcount_t i;
+
+	for (i = num_words - 1; i >= 0; --i) {
+		if (left[i] > right[i]) {
+			return 1;
+		} else if (left[i] < right[i]) {
+			return -1;
+		}
+	}
+	return 0;
+}
+
+uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
+			   wordcount_t num_words)
+{
+
+	uECC_word_t diff = 0;
+	wordcount_t i;
+
+	for (i = num_words - 1; i >= 0; --i) {
+		diff |= (left[i] ^ right[i]);
+	}
+	return !(diff == 0);
+}
+
+uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
+{
+	return (p_true*(cond)) | (p_false*(!cond));
+}
+
+/* Computes result = left - right, returning borrow, in constant time.
+ * Can modify in place. */
+uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
+			 const uECC_word_t *right, wordcount_t num_words)
+{
+	uECC_word_t borrow = 0;
+	wordcount_t i;
+	for (i = 0; i < num_words; ++i) {
+		uECC_word_t diff = left[i] - right[i] - borrow;
+		uECC_word_t val = (diff > left[i]);
+		borrow = cond_set(val, borrow, (diff != left[i]));
+
+		result[i] = diff;
+	}
+	return borrow;
+}
+
+/* Computes result = left + right, returning carry, in constant time.
+ * Can modify in place. */
+static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
+				const uECC_word_t *right, wordcount_t num_words)
+{
+	uECC_word_t carry = 0;
+	wordcount_t i;
+	for (i = 0; i < num_words; ++i) {
+		uECC_word_t sum = left[i] + right[i] + carry;
+		uECC_word_t val = (sum < left[i]);
+		carry = cond_set(val, carry, (sum != left[i]));
+		result[i] = sum;
+	}
+	return carry;
+}
+
+cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
+			 wordcount_t num_words)
+{
+	uECC_word_t tmp[NUM_ECC_WORDS];
+	uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
+	uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
+	return (!equal - 2 * neg);
+}
+
+/* Computes vli = vli >> 1. */
+static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words)
+{
+	uECC_word_t *end = vli;
+	uECC_word_t carry = 0;
+
+	vli += num_words;
+	while (vli-- > end) {
+		uECC_word_t temp = *vli;
+		*vli = (temp >> 1) | carry;
+		carry = temp << (uECC_WORD_BITS - 1);
+	}
+}
+
+static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0,
+		   uECC_word_t *r1, uECC_word_t *r2)
+{
+
+	uECC_dword_t p = (uECC_dword_t)a * b;
+	uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0;
+	r01 += p;
+	*r2 += (r01 < p);
+	*r1 = r01 >> uECC_WORD_BITS;
+	*r0 = (uECC_word_t)r01;
+
+}
+
+/* Computes result = left * right. Result must be 2 * num_words long. */
+static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left,
+			  const uECC_word_t *right, wordcount_t num_words)
+{
+
+	uECC_word_t r0 = 0;
+	uECC_word_t r1 = 0;
+	uECC_word_t r2 = 0;
+	wordcount_t i, k;
+
+	/* Compute each digit of result in sequence, maintaining the carries. */
+	for (k = 0; k < num_words; ++k) {
+
+		for (i = 0; i <= k; ++i) {
+			muladd(left[i], right[k - i], &r0, &r1, &r2);
+		}
+
+		result[k] = r0;
+		r0 = r1;
+		r1 = r2;
+		r2 = 0;
+	}
+
+	for (k = num_words; k < num_words * 2 - 1; ++k) {
+
+		for (i = (k + 1) - num_words; i < num_words; ++i) {
+			muladd(left[i], right[k - i], &r0, &r1, &r2);
+		}
+		result[k] = r0;
+		r0 = r1;
+		r1 = r2;
+		r2 = 0;
+	}
+	result[num_words * 2 - 1] = r0;
+}
+
+void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
+		     const uECC_word_t *right, const uECC_word_t *mod,
+		     wordcount_t num_words)
+{
+	uECC_word_t carry = uECC_vli_add(result, left, right, num_words);
+	if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) {
+	/* result > mod (result = mod + remainder), so subtract mod to get
+	 * remainder. */
+		uECC_vli_sub(result, result, mod, num_words);
+	}
+}
+
+void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
+		     const uECC_word_t *right, const uECC_word_t *mod,
+		     wordcount_t num_words)
+{
+	uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words);
+	if (l_borrow) {
+		/* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
+		 * we can get the correct result from result + mod (with overflow). */
+		uECC_vli_add(result, result, mod, num_words);
+	}
+}
+
+/* Computes result = product % mod, where product is 2N words long. */
+/* Currently only designed to work for curve_p or curve_n. */
+void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
+    		   const uECC_word_t *mod, wordcount_t num_words)
+{
+	uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
+	uECC_word_t tmp[2 * NUM_ECC_WORDS];
+	uECC_word_t *v[2] = {tmp, product};
+	uECC_word_t index;
+
+	/* Shift mod so its highest set bit is at the maximum position. */
+	bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
+			   uECC_vli_numBits(mod, num_words);
+	wordcount_t word_shift = shift / uECC_WORD_BITS;
+	wordcount_t bit_shift = shift % uECC_WORD_BITS;
+	uECC_word_t carry = 0;
+	uECC_vli_clear(mod_multiple, word_shift);
+	if (bit_shift > 0) {
+		for(index = 0; index < (uECC_word_t)num_words; ++index) {
+			mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
+			carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
+		}
+	} else {
+		uECC_vli_set(mod_multiple + word_shift, mod, num_words);
+	}
+
+	for (index = 1; shift >= 0; --shift) {
+		uECC_word_t borrow = 0;
+		wordcount_t i;
+		for (i = 0; i < num_words * 2; ++i) {
+			uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
+			if (diff != v[index][i]) {
+				borrow = (diff > v[index][i]);
+			}
+			v[1 - index][i] = diff;
+		}
+		/* Swap the index if there was no borrow */
+		index = !(index ^ borrow);
+		uECC_vli_rshift1(mod_multiple, num_words);
+		mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
+					       (uECC_WORD_BITS - 1);
+		uECC_vli_rshift1(mod_multiple + num_words, num_words);
+	}
+	uECC_vli_set(result, v[index], num_words);
+}
+
+void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
+		      const uECC_word_t *right, const uECC_word_t *mod,
+		      wordcount_t num_words)
+{
+	uECC_word_t product[2 * NUM_ECC_WORDS];
+	uECC_vli_mult(product, left, right, num_words);
+	uECC_vli_mmod(result, product, mod, num_words);
+}
+
+void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
+			   const uECC_word_t *right, uECC_Curve curve)
+{
+	uECC_word_t product[2 * NUM_ECC_WORDS];
+	uECC_vli_mult(product, left, right, curve->num_words);
+
+	curve->mmod_fast(result, product);
+}
+
+static void uECC_vli_modSquare_fast(uECC_word_t *result,
+				    const uECC_word_t *left,
+				    uECC_Curve curve)
+{
+	uECC_vli_modMult_fast(result, left, left, curve);
+}
+
+
+#define EVEN(vli) (!(vli[0] & 1))
+
+static void vli_modInv_update(uECC_word_t *uv,
+			      const uECC_word_t *mod,
+			      wordcount_t num_words)
+{
+
+	uECC_word_t carry = 0;
+
+	if (!EVEN(uv)) {
+		carry = uECC_vli_add(uv, uv, mod, num_words);
+	}
+	uECC_vli_rshift1(uv, num_words);
+	if (carry) {
+		uv[num_words - 1] |= HIGH_BIT_SET;
+	}
+}
+
+void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
+		     const uECC_word_t *mod, wordcount_t num_words)
+{
+	uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
+	uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
+	cmpresult_t cmpResult;
+
+	if (uECC_vli_isZero(input, num_words)) {
+		uECC_vli_clear(result, num_words);
+		return;
+	}
+
+	uECC_vli_set(a, input, num_words);
+	uECC_vli_set(b, mod, num_words);
+	uECC_vli_clear(u, num_words);
+	u[0] = 1;
+	uECC_vli_clear(v, num_words);
+	while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) {
+		if (EVEN(a)) {
+			uECC_vli_rshift1(a, num_words);
+      			vli_modInv_update(u, mod, num_words);
+    		} else if (EVEN(b)) {
+			uECC_vli_rshift1(b, num_words);
+			vli_modInv_update(v, mod, num_words);
+		} else if (cmpResult > 0) {
+			uECC_vli_sub(a, a, b, num_words);
+			uECC_vli_rshift1(a, num_words);
+			if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) {
+        			uECC_vli_add(u, u, mod, num_words);
+      			}
+      			uECC_vli_sub(u, u, v, num_words);
+      			vli_modInv_update(u, mod, num_words);
+    		} else {
+      			uECC_vli_sub(b, b, a, num_words);
+      			uECC_vli_rshift1(b, num_words);
+      			if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) {
+        			uECC_vli_add(v, v, mod, num_words);
+      			}
+      			uECC_vli_sub(v, v, u, num_words);
+      			vli_modInv_update(v, mod, num_words);
+    		}
+  	}
+  	uECC_vli_set(result, u, num_words);
+}
+
+/* ------ Point operations ------ */
+
+void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
+			     uECC_word_t * Z1, uECC_Curve curve)
+{
+	/* t1 = X, t2 = Y, t3 = Z */
+	uECC_word_t t4[NUM_ECC_WORDS];
+	uECC_word_t t5[NUM_ECC_WORDS];
+	wordcount_t num_words = curve->num_words;
+
+	if (uECC_vli_isZero(Z1, num_words)) {
+		return;
+	}
+
+	uECC_vli_modSquare_fast(t4, Y1, curve);   /* t4 = y1^2 */
+	uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
+	uECC_vli_modSquare_fast(t4, t4, curve);   /* t4 = y1^4 */
+	uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
+	uECC_vli_modSquare_fast(Z1, Z1, curve);   /* t3 = z1^2 */
+
+	uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */
+	uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */
+	uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */
+	uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
+
+	uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */
+	uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */
+	if (uECC_vli_testBit(X1, 0)) {
+		uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words);
+		uECC_vli_rshift1(X1, num_words);
+		X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
+	} else {
+		uECC_vli_rshift1(X1, num_words);
+	}
+
+	/* t1 = 3/2*(x1^2 - z1^4) = B */
+	uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
+	uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */
+	uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */
+	uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */
+	uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
+	/* t4 = B * (A - x3) - y1^4 = y3: */
+	uECC_vli_modSub(t4, X1, t4, curve->p, num_words);
+
+	uECC_vli_set(X1, Z1, num_words);
+	uECC_vli_set(Z1, Y1, num_words);
+	uECC_vli_set(Y1, t4, num_words);
+}
+
+void x_side_default(uECC_word_t *result,
+		    const uECC_word_t *x,
+		    uECC_Curve curve)
+{
+	uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
+	wordcount_t num_words = curve->num_words;
+
+	uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
+	uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */
+	uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
+	/* r = x^3 - 3x + b: */
+	uECC_vli_modAdd(result, result, curve->b, curve->p, num_words);
+}
+
+uECC_Curve uECC_secp256r1(void)
+{
+	return &curve_secp256r1;
+}
+
+void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
+{
+	unsigned int tmp[NUM_ECC_WORDS];
+	int carry;
+
+	/* t */
+	uECC_vli_set(result, product, NUM_ECC_WORDS);
+
+	/* s1 */
+	tmp[0] = tmp[1] = tmp[2] = 0;
+	tmp[3] = product[11];
+	tmp[4] = product[12];
+	tmp[5] = product[13];
+	tmp[6] = product[14];
+	tmp[7] = product[15];
+	carry = uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
+	carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
+
+	/* s2 */
+	tmp[3] = product[12];
+	tmp[4] = product[13];
+	tmp[5] = product[14];
+	tmp[6] = product[15];
+	tmp[7] = 0;
+	carry += uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
+	carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
+
+	/* s3 */
+	tmp[0] = product[8];
+	tmp[1] = product[9];
+	tmp[2] = product[10];
+	tmp[3] = tmp[4] = tmp[5] = 0;
+	tmp[6] = product[14];
+	tmp[7] = product[15];
+  	carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
+
+	/* s4 */
+	tmp[0] = product[9];
+	tmp[1] = product[10];
+	tmp[2] = product[11];
+	tmp[3] = product[13];
+	tmp[4] = product[14];
+	tmp[5] = product[15];
+	tmp[6] = product[13];
+	tmp[7] = product[8];
+	carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
+
+	/* d1 */
+	tmp[0] = product[11];
+	tmp[1] = product[12];
+	tmp[2] = product[13];
+	tmp[3] = tmp[4] = tmp[5] = 0;
+	tmp[6] = product[8];
+	tmp[7] = product[10];
+	carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
+
+	/* d2 */
+	tmp[0] = product[12];
+	tmp[1] = product[13];
+	tmp[2] = product[14];
+	tmp[3] = product[15];
+	tmp[4] = tmp[5] = 0;
+	tmp[6] = product[9];
+	tmp[7] = product[11];
+	carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
+
+	/* d3 */
+	tmp[0] = product[13];
+	tmp[1] = product[14];
+	tmp[2] = product[15];
+	tmp[3] = product[8];
+	tmp[4] = product[9];
+	tmp[5] = product[10];
+	tmp[6] = 0;
+	tmp[7] = product[12];
+	carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
+
+	/* d4 */
+	tmp[0] = product[14];
+	tmp[1] = product[15];
+	tmp[2] = 0;
+	tmp[3] = product[9];
+	tmp[4] = product[10];
+	tmp[5] = product[11];
+	tmp[6] = 0;
+	tmp[7] = product[13];
+	carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
+
+	if (carry < 0) {
+		do {
+			carry += uECC_vli_add(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
+		}
+		while (carry < 0);
+	} else  {
+		while (carry || 
+		       uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) {
+			carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
+		}
+	}
+}
+
+uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve)
+{
+	return uECC_vli_isZero(point, curve->num_words * 2);
+}
+
+void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
+	     uECC_Curve curve)
+{
+	uECC_word_t t1[NUM_ECC_WORDS];
+
+	uECC_vli_modSquare_fast(t1, Z, curve);    /* z^2 */
+	uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */
+	uECC_vli_modMult_fast(t1, t1, Z, curve);  /* z^3 */
+	uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
+}
+
+/* P = (x1, y1) => 2P, (x2, y2) => P' */
+static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
+				uECC_word_t * X2, uECC_word_t * Y2,
+				const uECC_word_t * const initial_Z,
+				uECC_Curve curve)
+{
+	uECC_word_t z[NUM_ECC_WORDS];
+	wordcount_t num_words = curve->num_words;
+	if (initial_Z) {
+		uECC_vli_set(z, initial_Z, num_words);
+	} else {
+		uECC_vli_clear(z, num_words);
+		z[0] = 1;
+	}
+
+	uECC_vli_set(X2, X1, num_words);
+	uECC_vli_set(Y2, Y1, num_words);
+
+	apply_z(X1, Y1, z, curve);
+	curve->double_jacobian(X1, Y1, z, curve);
+	apply_z(X2, Y2, z, curve);
+}
+
+void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
+	      uECC_word_t * X2, uECC_word_t * Y2,
+	      uECC_Curve curve)
+{
+	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
+	uECC_word_t t5[NUM_ECC_WORDS];
+	wordcount_t num_words = curve->num_words;
+
+	uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
+	uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
+	uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
+	uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
+	uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
+	uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */
+
+	uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
+	uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
+	uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
+	uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */
+	uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
+	uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */
+	uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
+
+	uECC_vli_set(X2, t5, num_words);
+}
+
+/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
+   Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
+   or P => P - Q, Q => P + Q
+ */
+static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1,
+		      uECC_word_t * X2, uECC_word_t * Y2,
+		      uECC_Curve curve)
+{
+	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
+	uECC_word_t t5[NUM_ECC_WORDS];
+	uECC_word_t t6[NUM_ECC_WORDS];
+	uECC_word_t t7[NUM_ECC_WORDS];
+	wordcount_t num_words = curve->num_words;
+
+	uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
+	uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
+	uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
+	uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
+	uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */
+	uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
+
+	uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */
+	uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */
+	uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */
+	uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */
+	uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */
+
+	uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */
+	uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */
+	/* t4 = (y2 - y1)*(B - x3) - E = y3: */
+	uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words);
+
+	uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */
+	uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */
+	uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */
+	uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */
+	/* t2 = (y2+y1)*(x3' - B) - E = y3': */
+	uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words);
+
+	uECC_vli_set(X1, t7, num_words);
+}
+
+void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
+		   const uECC_word_t * scalar,
+		   const uECC_word_t * initial_Z,
+		   bitcount_t num_bits, uECC_Curve curve) 
+{
+	/* R0 and R1 */
+	uECC_word_t Rx[2][NUM_ECC_WORDS];
+	uECC_word_t Ry[2][NUM_ECC_WORDS];
+	uECC_word_t z[NUM_ECC_WORDS];
+	bitcount_t i;
+	uECC_word_t nb;
+	wordcount_t num_words = curve->num_words;
+
+	uECC_vli_set(Rx[1], point, num_words);
+  	uECC_vli_set(Ry[1], point + num_words, num_words);
+
+	XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve);
+
+	for (i = num_bits - 2; i > 0; --i) {
+		nb = !uECC_vli_testBit(scalar, i);
+		XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
+		XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
+	}
+
+	nb = !uECC_vli_testBit(scalar, 0);
+	XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
+
+	/* Find final 1/Z value. */
+	uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */
+	uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */
+	uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */
+	uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/
+	/* yP / (xP * Yb * (X1 - X0)) */
+	uECC_vli_modMult_fast(z, z, point + num_words, curve);
+	/* Xb * yP / (xP * Yb * (X1 - X0)) */
+	uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve);
+	/* End 1/Z calculation */
+
+	XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
+	apply_z(Rx[0], Ry[0], z, curve);
+
+	uECC_vli_set(result, Rx[0], num_words);
+	uECC_vli_set(result + num_words, Ry[0], num_words);
+}
+
+uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
+			 uECC_word_t *k1, uECC_Curve curve)
+{
+
+	wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+
+	bitcount_t num_n_bits = curve->num_n_bits;
+
+	uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
+			     (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
+			     uECC_vli_testBit(k0, num_n_bits));
+
+	uECC_vli_add(k1, k0, curve->n, num_n_words);
+
+	return carry;
+}
+
+uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
+					uECC_word_t *private_key,
+					uECC_Curve curve)
+{
+
+	uECC_word_t tmp1[NUM_ECC_WORDS];
+ 	uECC_word_t tmp2[NUM_ECC_WORDS];
+	uECC_word_t *p2[2] = {tmp1, tmp2};
+	uECC_word_t carry;
+
+	/* Regularize the bitcount for the private key so that attackers cannot
+	 * use a side channel attack to learn the number of leading zeros. */
+	carry = regularize_k(private_key, tmp1, tmp2, curve);
+
+	EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
+
+	if (EccPoint_isZero(result, curve)) {
+		return 0;
+	}
+	return 1;
+}
+
+/* Converts an integer in uECC native format to big-endian bytes. */
+void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
+			    const unsigned int *native)
+{
+	wordcount_t i;
+	for (i = 0; i < num_bytes; ++i) {
+		unsigned b = num_bytes - 1 - i;
+		bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
+	}
+}
+
+/* Converts big-endian bytes to an integer in uECC native format. */
+void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
+			    int num_bytes)
+{
+	wordcount_t i;
+	uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
+	for (i = 0; i < num_bytes; ++i) {
+		unsigned b = num_bytes - 1 - i;
+		native[b / uECC_WORD_SIZE] |=
+			(uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
+  	}
+}
+
+int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
+			     wordcount_t num_words)
+{
+	uECC_word_t mask = (uECC_word_t)-1;
+	uECC_word_t tries;
+	bitcount_t num_bits = uECC_vli_numBits(top, num_words);
+
+	if (!g_rng_function) {
+		return 0;
+	}
+
+	for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+		if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
+      			return 0;
+    		}
+		random[num_words - 1] &=
+        		mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
+		if (!uECC_vli_isZero(random, num_words) &&
+			uECC_vli_cmp(top, random, num_words) == 1) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
+int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve)
+{
+	uECC_word_t tmp1[NUM_ECC_WORDS];
+	uECC_word_t tmp2[NUM_ECC_WORDS];
+	wordcount_t num_words = curve->num_words;
+
+	/* The point at infinity is invalid. */
+	if (EccPoint_isZero(point, curve)) {
+		return -1;
+	}
+
+	/* x and y must be smaller than p. */
+	if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 ||
+		uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) {
+		return -2;
+	}
+
+	uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
+	curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
+
+	/* Make sure that y^2 == x^3 + ax + b */
+	if (uECC_vli_equal(tmp1, tmp2, num_words) != 0)
+		return -3;
+
+	return 0;
+}
+
+int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve)
+{
+
+	uECC_word_t _public[NUM_ECC_WORDS * 2];
+
+	uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
+	uECC_vli_bytesToNative(
+	_public + curve->num_words,
+	public_key + curve->num_bytes,
+	curve->num_bytes);
+
+	if (uECC_vli_cmp_unsafe(_public, curve->G, NUM_ECC_WORDS * 2) == 0) {
+		return -4;
+	}
+
+	return uECC_valid_point(_public, curve);
+}
+
+int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
+			    uECC_Curve curve)
+{
+
+	uECC_word_t _private[NUM_ECC_WORDS];
+	uECC_word_t _public[NUM_ECC_WORDS * 2];
+
+	uECC_vli_bytesToNative(
+	_private,
+	private_key,
+	BITS_TO_BYTES(curve->num_n_bits));
+
+	/* Make sure the private key is in the range [1, n-1]. */
+	if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) {
+		return 0;
+	}
+
+	if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) {
+		return 0;
+	}
+
+	/* Compute public key. */
+	if (!EccPoint_compute_public_key(_public, _private, curve)) {
+		return 0;
+	}
+
+	uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public);
+	uECC_vli_nativeToBytes(
+	public_key +
+	curve->num_bytes, curve->num_bytes, _public + curve->num_words);
+	return 1;
+}
+
+
+
diff --git a/tinycrypt/src/ecc_dh.c b/tinycrypt/src/ecc_dh.c
new file mode 100644
index 0000000..e5257d2
--- /dev/null
+++ b/tinycrypt/src/ecc_dh.c
@@ -0,0 +1,200 @@
+/* ec_dh.c - TinyCrypt implementation of EC-DH */
+
+/* 
+ * Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <tinycrypt/constants.h>
+#include <tinycrypt/ecc.h>
+#include <tinycrypt/ecc_dh.h>
+#include <string.h>
+
+#if default_RNG_defined
+static uECC_RNG_Function g_rng_function = &default_CSPRNG;
+#else
+static uECC_RNG_Function g_rng_function = 0;
+#endif
+
+int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
+			 unsigned int *d, uECC_Curve curve)
+{
+
+	uECC_word_t _private[NUM_ECC_WORDS];
+	uECC_word_t _public[NUM_ECC_WORDS * 2];
+
+	/* This function is designed for test purposes-only (such as validating NIST
+	 * test vectors) as it uses a provided value for d instead of generating
+	 * it uniformly at random. */
+	memcpy (_private, d, NUM_ECC_BYTES);
+
+	/* Computing public-key from private: */
+	if (EccPoint_compute_public_key(_public, _private, curve)) {
+
+		/* Converting buffers to correct bit order: */
+		uECC_vli_nativeToBytes(private_key,
+				       BITS_TO_BYTES(curve->num_n_bits),
+				       _private);
+		uECC_vli_nativeToBytes(public_key,
+				       curve->num_bytes,
+				       _public);
+		uECC_vli_nativeToBytes(public_key + curve->num_bytes,
+				       curve->num_bytes,
+				       _public + curve->num_words);
+
+		/* erasing temporary buffer used to store secret: */
+		memset(_private, 0, NUM_ECC_BYTES);
+
+		return 1;
+	}
+	return 0;
+}
+
+int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve)
+{
+
+	uECC_word_t _random[NUM_ECC_WORDS * 2];
+	uECC_word_t _private[NUM_ECC_WORDS];
+	uECC_word_t _public[NUM_ECC_WORDS * 2];
+	uECC_word_t tries;
+
+	for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+		/* Generating _private uniformly at random: */
+		uECC_RNG_Function rng_function = uECC_get_rng();
+		if (!rng_function ||
+			!rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) {
+        		return 0;
+		}
+
+		/* computing modular reduction of _random (see FIPS 186.4 B.4.1): */
+		uECC_vli_mmod(_private, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits));
+
+		/* Computing public-key from private: */
+		if (EccPoint_compute_public_key(_public, _private, curve)) {
+
+			/* Converting buffers to correct bit order: */
+			uECC_vli_nativeToBytes(private_key,
+					       BITS_TO_BYTES(curve->num_n_bits),
+					       _private);
+			uECC_vli_nativeToBytes(public_key,
+					       curve->num_bytes,
+					       _public);
+			uECC_vli_nativeToBytes(public_key + curve->num_bytes,
+ 					       curve->num_bytes,
+					       _public + curve->num_words);
+
+			/* erasing temporary buffer that stored secret: */
+			memset(_private, 0, NUM_ECC_BYTES);
+
+      			return 1;
+    		}
+  	}
+	return 0;
+}
+
+int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
+		       uint8_t *secret, uECC_Curve curve)
+{
+
+	uECC_word_t _public[NUM_ECC_WORDS * 2];
+	uECC_word_t _private[NUM_ECC_WORDS];
+
+	uECC_word_t tmp[NUM_ECC_WORDS];
+	uECC_word_t *p2[2] = {_private, tmp};
+	uECC_word_t *initial_Z = 0;
+	uECC_word_t carry;
+	wordcount_t num_words = curve->num_words;
+	wordcount_t num_bytes = curve->num_bytes;
+	int r;
+
+	/* Converting buffers to correct bit order: */
+	uECC_vli_bytesToNative(_private,
+      			       private_key,
+			       BITS_TO_BYTES(curve->num_n_bits));
+	uECC_vli_bytesToNative(_public,
+      			       public_key,
+			       num_bytes);
+	uECC_vli_bytesToNative(_public + num_words,
+			       public_key + num_bytes,
+			       num_bytes);
+
+	/* Regularize the bitcount for the private key so that attackers cannot use a
+	 * side channel attack to learn the number of leading zeros. */
+	carry = regularize_k(_private, _private, tmp, curve);
+
+	/* If an RNG function was specified, try to get a random initial Z value to
+	 * improve protection against side-channel attacks. */
+	if (g_rng_function) {
+		if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) {
+			r = 0;
+			goto clear_and_out;
+    		}
+    		initial_Z = p2[carry];
+  	}
+
+	EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1,
+		      curve);
+
+	uECC_vli_nativeToBytes(secret, num_bytes, _public);
+	r = !EccPoint_isZero(_public, curve);
+
+clear_and_out:
+	/* erasing temporary buffer used to store secret: */
+	memset(p2, 0, sizeof(p2));
+	__asm__ __volatile__("" :: "g"(p2) : "memory");
+	memset(tmp, 0, sizeof(tmp));
+	__asm__ __volatile__("" :: "g"(tmp) : "memory");
+	memset(_private, 0, sizeof(_private));
+	__asm__ __volatile__("" :: "g"(_private) : "memory");
+
+	return r;
+}
diff --git a/tinycrypt/src/ecc_dsa.c b/tinycrypt/src/ecc_dsa.c
new file mode 100644
index 0000000..064dfe5
--- /dev/null
+++ b/tinycrypt/src/ecc_dsa.c
@@ -0,0 +1,295 @@
+/* ec_dsa.c - TinyCrypt implementation of EC-DSA */
+
+/* Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.*/
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/constants.h>
+#include <tinycrypt/ecc.h>
+#include <tinycrypt/ecc_dsa.h>
+
+#if default_RNG_defined
+static uECC_RNG_Function g_rng_function = &default_CSPRNG;
+#else
+static uECC_RNG_Function g_rng_function = 0;
+#endif
+
+static void bits2int(uECC_word_t *native, const uint8_t *bits,
+		     unsigned bits_size, uECC_Curve curve)
+{
+	unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits);
+	unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+	int shift;
+	uECC_word_t carry;
+	uECC_word_t *ptr;
+
+	if (bits_size > num_n_bytes) {
+		bits_size = num_n_bytes;
+	}
+
+	uECC_vli_clear(native, num_n_words);
+	uECC_vli_bytesToNative(native, bits, bits_size);
+	if (bits_size * 8 <= (unsigned)curve->num_n_bits) {
+		return;
+	}
+	shift = bits_size * 8 - curve->num_n_bits;
+	carry = 0;
+	ptr = native + num_n_words;
+	while (ptr-- > native) {
+		uECC_word_t temp = *ptr;
+		*ptr = (temp >> shift) | carry;
+		carry = temp << (uECC_WORD_BITS - shift);
+	}
+
+	/* Reduce mod curve_n */
+	if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) {
+		uECC_vli_sub(native, native, curve->n, num_n_words);
+	}
+}
+
+int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
+		     unsigned hash_size, uECC_word_t *k, uint8_t *signature,
+		     uECC_Curve curve)
+{
+
+	uECC_word_t tmp[NUM_ECC_WORDS];
+	uECC_word_t s[NUM_ECC_WORDS];
+	uECC_word_t *k2[2] = {tmp, s};
+	uECC_word_t p[NUM_ECC_WORDS * 2];
+	uECC_word_t carry;
+	wordcount_t num_words = curve->num_words;
+	wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+	bitcount_t num_n_bits = curve->num_n_bits;
+
+	/* Make sure 0 < k < curve_n */
+  	if (uECC_vli_isZero(k, num_words) ||
+	    uECC_vli_cmp(curve->n, k, num_n_words) != 1) {
+		return 0;
+	}
+
+	carry = regularize_k(k, tmp, s, curve);
+	EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
+	if (uECC_vli_isZero(p, num_words)) {
+		return 0;
+	}
+
+	/* If an RNG function was specified, get a random number
+	to prevent side channel analysis of k. */
+	if (!g_rng_function) {
+		uECC_vli_clear(tmp, num_n_words);
+		tmp[0] = 1;
+	}
+	else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) {
+		return 0;
+	}
+
+	/* Prevent side channel analysis of uECC_vli_modInv() to determine
+	bits of k / the private key by premultiplying by a random number */
+	uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */
+	uECC_vli_modInv(k, k, curve->n, num_n_words);       /* k = 1 / k' */
+	uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */
+
+	uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */
+
+	/* tmp = d: */
+	uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits));
+
+	s[num_n_words - 1] = 0;
+	uECC_vli_set(s, p, num_words);
+	uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */
+
+	bits2int(tmp, message_hash, hash_size, curve);
+	uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
+	uECC_vli_modMult(s, s, k, curve->n, num_n_words);  /* s = (e + r*d) / k */
+	if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
+		return 0;
+	}
+
+	uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s);
+	return 1;
+}
+
+int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash,
+	      unsigned hash_size, uint8_t *signature, uECC_Curve curve)
+{
+	      uECC_word_t _random[2*NUM_ECC_WORDS];
+	      uECC_word_t k[NUM_ECC_WORDS];
+	      uECC_word_t tries;
+
+	for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+		/* Generating _random uniformly at random: */
+		uECC_RNG_Function rng_function = uECC_get_rng();
+		if (!rng_function ||
+		    !rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) {
+			return 0;
+		}
+
+		// computing k as modular reduction of _random (see FIPS 186.4 B.5.1):
+		uECC_vli_mmod(k, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits));
+
+		if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, 
+		    curve)) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static bitcount_t smax(bitcount_t a, bitcount_t b)
+{
+	return (a > b ? a : b);
+}
+
+int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash,
+		unsigned hash_size, const uint8_t *signature,
+	        uECC_Curve curve)
+{
+
+	uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS];
+	uECC_word_t z[NUM_ECC_WORDS];
+	uECC_word_t sum[NUM_ECC_WORDS * 2];
+	uECC_word_t rx[NUM_ECC_WORDS];
+	uECC_word_t ry[NUM_ECC_WORDS];
+	uECC_word_t tx[NUM_ECC_WORDS];
+	uECC_word_t ty[NUM_ECC_WORDS];
+	uECC_word_t tz[NUM_ECC_WORDS];
+	const uECC_word_t *points[4];
+	const uECC_word_t *point;
+	bitcount_t num_bits;
+	bitcount_t i;
+
+	uECC_word_t _public[NUM_ECC_WORDS * 2];
+	uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS];
+	wordcount_t num_words = curve->num_words;
+	wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+
+	rx[num_n_words - 1] = 0;
+	r[num_n_words - 1] = 0;
+	s[num_n_words - 1] = 0;
+
+	uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
+	uECC_vli_bytesToNative(_public + num_words, public_key + curve->num_bytes,
+			       curve->num_bytes);
+	uECC_vli_bytesToNative(r, signature, curve->num_bytes);
+	uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
+
+	/* r, s must not be 0. */
+	if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
+		return 0;
+	}
+
+	/* r, s must be < n. */
+	if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 ||
+	    uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) {
+		return 0;
+	}
+
+	/* Calculate u1 and u2. */
+	uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
+	u1[num_n_words - 1] = 0;
+	bits2int(u1, message_hash, hash_size, curve);
+	uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
+	uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
+
+	/* Calculate sum = G + Q. */
+	uECC_vli_set(sum, _public, num_words);
+	uECC_vli_set(sum + num_words, _public + num_words, num_words);
+	uECC_vli_set(tx, curve->G, num_words);
+	uECC_vli_set(ty, curve->G + num_words, num_words);
+	uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
+	XYcZ_add(tx, ty, sum, sum + num_words, curve);
+	uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
+	apply_z(sum, sum + num_words, z, curve);
+
+	/* Use Shamir's trick to calculate u1*G + u2*Q */
+	points[0] = 0;
+	points[1] = curve->G;
+	points[2] = _public;
+	points[3] = sum;
+	num_bits = smax(uECC_vli_numBits(u1, num_n_words),
+	uECC_vli_numBits(u2, num_n_words));
+
+	point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
+                       ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
+	uECC_vli_set(rx, point, num_words);
+	uECC_vli_set(ry, point + num_words, num_words);
+	uECC_vli_clear(z, num_words);
+	z[0] = 1;
+
+	for (i = num_bits - 2; i >= 0; --i) {
+		uECC_word_t index;
+		curve->double_jacobian(rx, ry, z, curve);
+
+		index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1);
+		point = points[index];
+		if (point) {
+			uECC_vli_set(tx, point, num_words);
+			uECC_vli_set(ty, point + num_words, num_words);
+			apply_z(tx, ty, z, curve);
+			uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
+			XYcZ_add(tx, ty, rx, ry, curve);
+			uECC_vli_modMult_fast(z, z, tz, curve);
+		}
+  	}
+
+	uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
+	apply_z(rx, ry, z, curve);
+
+	/* v = x1 (mod n) */
+	if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) {
+		uECC_vli_sub(rx, rx, curve->n, num_n_words);
+	}
+
+	/* Accept only if v == r. */
+	return (int)(uECC_vli_equal(rx, r, num_words) == 0);
+}
+
diff --git a/tinycrypt/src/ecc_platform_specific.c b/tinycrypt/src/ecc_platform_specific.c
new file mode 100644
index 0000000..1867988
--- /dev/null
+++ b/tinycrypt/src/ecc_platform_specific.c
@@ -0,0 +1,105 @@
+/*  uECC_platform_specific.c - Implementation of platform specific functions*/
+
+/* Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.*/
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  uECC_platform_specific.c -- Implementation of platform specific functions
+ */
+
+
+#if defined(unix) || defined(__linux__) || defined(__unix__) || \
+    defined(__unix) |  (defined(__APPLE__) && defined(__MACH__)) || \
+    defined(uECC_POSIX)
+
+/* Some POSIX-like system with /dev/urandom or /dev/random. */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <stdint.h>
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+int default_CSPRNG(uint8_t *dest, unsigned int size) {
+
+  /* input sanity check: */
+  if (dest == (uint8_t *) 0 || (size <= 0))
+    return 0;
+
+  int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
+  if (fd == -1) {
+    fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
+    if (fd == -1) {
+      return 0;
+    }
+  }
+
+  char *ptr = (char *)dest;
+  size_t left = (size_t) size;
+  while (left > 0) {
+    ssize_t bytes_read = read(fd, ptr, left);
+    if (bytes_read <= 0) { // read failed
+      close(fd);
+      return 0;
+    }
+    left -= bytes_read;
+    ptr += bytes_read;
+  }
+
+  close(fd);
+  return 1;
+}
+
+#endif /* platform */
+
diff --git a/tinycrypt/src/hmac.c b/tinycrypt/src/hmac.c
new file mode 100644
index 0000000..89878ce
--- /dev/null
+++ b/tinycrypt/src/hmac.c
@@ -0,0 +1,148 @@
+/* hmac.c - TinyCrypt implementation of the HMAC algorithm */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/hmac.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size)
+{
+	const uint8_t inner_pad = (uint8_t) 0x36;
+	const uint8_t outer_pad = (uint8_t) 0x5c;
+	unsigned int i;
+
+	for (i = 0; i < key_size; ++i) {
+		key[i] = inner_pad ^ new_key[i];
+		key[i + TC_SHA256_BLOCK_SIZE] = outer_pad ^ new_key[i];
+	}
+	for (; i < TC_SHA256_BLOCK_SIZE; ++i) {
+		key[i] = inner_pad; key[i + TC_SHA256_BLOCK_SIZE] = outer_pad;
+	}
+}
+
+int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
+		    unsigned int key_size)
+{
+
+	/* input sanity check: */
+	if (ctx == (TCHmacState_t) 0 ||
+	    key == (const uint8_t *) 0 ||
+	    key_size == 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	const uint8_t dummy_key[key_size];
+	struct tc_hmac_state_struct dummy_state;
+
+	if (key_size <= TC_SHA256_BLOCK_SIZE) {
+		/*
+		 * The next three lines consist of dummy calls just to avoid
+		 * certain timing attacks. Without these dummy calls,
+		 * adversaries would be able to learn whether the key_size is
+		 * greater than TC_SHA256_BLOCK_SIZE by measuring the time
+		 * consumed in this process.
+		 */
+		(void)tc_sha256_init(&dummy_state.hash_state);
+		(void)tc_sha256_update(&dummy_state.hash_state,
+				       dummy_key,
+				       key_size);
+		(void)tc_sha256_final(&dummy_state.key[TC_SHA256_DIGEST_SIZE],
+				      &dummy_state.hash_state);
+
+		/* Actual code for when key_size <= TC_SHA256_BLOCK_SIZE: */
+		rekey(ctx->key, key, key_size);
+	} else {
+		(void)tc_sha256_init(&ctx->hash_state);
+		(void)tc_sha256_update(&ctx->hash_state, key, key_size);
+		(void)tc_sha256_final(&ctx->key[TC_SHA256_DIGEST_SIZE],
+				      &ctx->hash_state);
+		rekey(ctx->key,
+		      &ctx->key[TC_SHA256_DIGEST_SIZE],
+		      TC_SHA256_DIGEST_SIZE);
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_init(TCHmacState_t ctx)
+{
+
+	/* input sanity check: */
+	if (ctx == (TCHmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+  (void) tc_sha256_init(&ctx->hash_state);
+  (void) tc_sha256_update(&ctx->hash_state, ctx->key, TC_SHA256_BLOCK_SIZE);
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_update(TCHmacState_t ctx,
+		   const void *data,
+		   unsigned int data_length)
+{
+
+	/* input sanity check: */
+	if (ctx == (TCHmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	(void)tc_sha256_update(&ctx->hash_state, data, data_length);
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx)
+{
+
+	/* input sanity check: */
+	if (tag == (uint8_t *) 0 ||
+	    taglen != TC_SHA256_DIGEST_SIZE ||
+	    ctx == (TCHmacState_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	(void) tc_sha256_final(tag, &ctx->hash_state);
+
+	(void)tc_sha256_init(&ctx->hash_state);
+	(void)tc_sha256_update(&ctx->hash_state,
+			       &ctx->key[TC_SHA256_BLOCK_SIZE],
+				TC_SHA256_BLOCK_SIZE);
+	(void)tc_sha256_update(&ctx->hash_state, tag, TC_SHA256_DIGEST_SIZE);
+	(void)tc_sha256_final(tag, &ctx->hash_state);
+
+	/* destroy the current state */
+	_set(ctx, 0, sizeof(*ctx));
+
+	return TC_CRYPTO_SUCCESS;
+}
diff --git a/tinycrypt/src/hmac_prng.c b/tinycrypt/src/hmac_prng.c
new file mode 100644
index 0000000..68b5b1f
--- /dev/null
+++ b/tinycrypt/src/hmac_prng.c
@@ -0,0 +1,212 @@
+/* hmac_prng.c - TinyCrypt implementation of HMAC-PRNG */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/hmac_prng.h>
+#include <tinycrypt/hmac.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+/*
+ * min bytes in the seed string.
+ * MIN_SLEN*8 must be at least the expected security level.
+ */
+static const unsigned int MIN_SLEN = 32;
+
+/*
+ * max bytes in the seed string;
+ * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
+ */
+static const unsigned int MAX_SLEN = UINT32_MAX;
+
+/*
+ * max bytes in the personalization string;
+ * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
+ */
+static const unsigned int MAX_PLEN = UINT32_MAX;
+
+/*
+ * max bytes in the additional_info string;
+ * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
+ */
+static const unsigned int MAX_ALEN = UINT32_MAX;
+
+/*
+ * max number of generates between re-seeds;
+ * TinyCrypt accepts up to (2^32 - 1) which is the maximal value of
+ * a 32-bit unsigned int variable, while SP800-90A specifies a maximum of 2^48.
+ */
+static const unsigned int MAX_GENS = UINT32_MAX;
+
+/*
+ * maximum bytes per generate call;
+ * SP800-90A specifies a maximum up to 2^19.
+ */
+static const unsigned int  MAX_OUT = (1 << 19);
+
+/*
+ * Assumes: prng != NULL, e != NULL, len >= 0.
+ */
+static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len)
+{
+	const uint8_t separator0 = 0x00;
+	const uint8_t separator1 = 0x01;
+
+	/* use current state, e and separator 0 to compute a new prng key: */
+	(void)tc_hmac_init(&prng->h);
+	(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+	(void)tc_hmac_update(&prng->h, &separator0, sizeof(separator0));
+	(void)tc_hmac_update(&prng->h, e, len);
+	(void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);
+	/* configure the new prng key into the prng's instance of hmac */
+	(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
+
+	/* use the new key to compute a new state variable v */
+	(void)tc_hmac_init(&prng->h);
+	(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+	(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
+
+	/* use current state, e and separator 1 to compute a new prng key: */
+	(void)tc_hmac_init(&prng->h);
+	(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+	(void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1));
+	(void)tc_hmac_update(&prng->h, e, len);
+	(void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);
+	/* configure the new prng key into the prng's instance of hmac */
+	(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
+
+	/* use the new key to compute a new state variable v */
+	(void)tc_hmac_init(&prng->h);
+	(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+	(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
+}
+
+int tc_hmac_prng_init(TCHmacPrng_t prng,
+		      const uint8_t *personalization,
+		      unsigned int plen)
+{
+
+	/* input sanity check: */
+	if (prng == (TCHmacPrng_t) 0 ||
+	    personalization == (uint8_t *) 0 ||
+	    plen > MAX_PLEN) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/* put the generator into a known state: */
+	_set(prng->key, 0x00, sizeof(prng->key));
+	_set(prng->v, 0x01, sizeof(prng->v));
+	tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
+	/* update assumes SOME key has been configured into HMAC */
+
+	update(prng, personalization, plen);
+
+	/* force a reseed before allowing tc_hmac_prng_generate to succeed: */
+	prng->countdown = 0;
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_prng_reseed(TCHmacPrng_t prng,
+			const uint8_t *seed,
+			unsigned int seedlen,
+			const uint8_t *additional_input,
+			unsigned int additionallen)
+{
+
+	/* input sanity check: */
+	if (prng == (TCHmacPrng_t) 0 ||
+	    seed == (const uint8_t *) 0 ||
+	    seedlen < MIN_SLEN ||
+	    seedlen > MAX_SLEN) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	if (additional_input != (const uint8_t *) 0) {
+		/*
+		 * Abort if additional_input is provided but has inappropriate
+		 * length
+		 */
+		if (additionallen == 0 ||
+		    additionallen > MAX_ALEN) {
+			return TC_CRYPTO_FAIL;
+		} else {
+		/* call update for the seed and additional_input */
+		update(prng, seed, seedlen);
+		update(prng, additional_input, additionallen);
+		}
+	} else {
+		/* call update only for the seed */
+		update(prng, seed, seedlen);
+	}
+
+	/* ... and enable hmac_prng_generate */
+	prng->countdown = MAX_GENS;
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng)
+{
+	unsigned int bufferlen;
+
+	/* input sanity check: */
+	if (out == (uint8_t *) 0 ||
+	    prng == (TCHmacPrng_t) 0 ||
+	    outlen == 0 ||
+	    outlen > MAX_OUT) {
+		return TC_CRYPTO_FAIL;
+	} else if (prng->countdown == 0) {
+		return TC_HMAC_PRNG_RESEED_REQ;
+	}
+
+	prng->countdown--;
+
+	while (outlen != 0) {
+		/* operate HMAC in OFB mode to create "random" outputs */
+		(void)tc_hmac_init(&prng->h);
+		(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+		(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
+
+		bufferlen = (TC_SHA256_DIGEST_SIZE > outlen) ?
+			outlen : TC_SHA256_DIGEST_SIZE;
+		(void)_copy(out, bufferlen, prng->v, bufferlen);
+
+		out += bufferlen;
+		outlen = (outlen > TC_SHA256_DIGEST_SIZE) ?
+			(outlen - TC_SHA256_DIGEST_SIZE) : 0;
+	}
+
+	/* block future PRNG compromises from revealing past state */
+	update(prng, prng->v, TC_SHA256_DIGEST_SIZE);
+
+	return TC_CRYPTO_SUCCESS;
+}
diff --git a/tinycrypt/src/sha256.c b/tinycrypt/src/sha256.c
new file mode 100644
index 0000000..b4efd20
--- /dev/null
+++ b/tinycrypt/src/sha256.c
@@ -0,0 +1,217 @@
+/* sha256.c - TinyCrypt SHA-256 crypto hash algorithm implementation */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/sha256.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+static void compress(unsigned int *iv, const uint8_t *data);
+
+int tc_sha256_init(TCSha256State_t s)
+{
+	/* input sanity check: */
+	if (s == (TCSha256State_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	/*
+	 * Setting the initial state values.
+	 * These values correspond to the first 32 bits of the fractional parts
+	 * of the square roots of the first 8 primes: 2, 3, 5, 7, 11, 13, 17
+	 * and 19.
+	 */
+	_set((uint8_t *) s, 0x00, sizeof(*s));
+	s->iv[0] = 0x6a09e667;
+	s->iv[1] = 0xbb67ae85;
+	s->iv[2] = 0x3c6ef372;
+	s->iv[3] = 0xa54ff53a;
+	s->iv[4] = 0x510e527f;
+	s->iv[5] = 0x9b05688c;
+	s->iv[6] = 0x1f83d9ab;
+	s->iv[7] = 0x5be0cd19;
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_sha256_update(TCSha256State_t s, const uint8_t *data, size_t datalen)
+{
+	/* input sanity check: */
+	if (s == (TCSha256State_t) 0 ||
+	    data == (void *) 0) {
+		return TC_CRYPTO_FAIL;
+	} else if (datalen == 0) {
+		return TC_CRYPTO_SUCCESS;
+	}
+
+	while (datalen-- > 0) {
+		s->leftover[s->leftover_offset++] = *(data++);
+		if (s->leftover_offset >= TC_SHA256_BLOCK_SIZE) {
+			compress(s->iv, s->leftover);
+			s->leftover_offset = 0;
+			s->bits_hashed += (TC_SHA256_BLOCK_SIZE << 3);
+		}
+	}
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+int tc_sha256_final(uint8_t *digest, TCSha256State_t s)
+{
+	unsigned int i;
+
+	/* input sanity check: */
+	if (digest == (uint8_t *) 0 ||
+	    s == (TCSha256State_t) 0) {
+		return TC_CRYPTO_FAIL;
+	}
+
+	s->bits_hashed += (s->leftover_offset << 3);
+
+	s->leftover[s->leftover_offset++] = 0x80; /* always room for one byte */
+	if (s->leftover_offset > (sizeof(s->leftover) - 8)) {
+		/* there is not room for all the padding in this block */
+		_set(s->leftover + s->leftover_offset, 0x00,
+		     sizeof(s->leftover) - s->leftover_offset);
+		compress(s->iv, s->leftover);
+		s->leftover_offset = 0;
+	}
+
+	/* add the padding and the length in big-Endian format */
+	_set(s->leftover + s->leftover_offset, 0x00,
+	     sizeof(s->leftover) - 8 - s->leftover_offset);
+	s->leftover[sizeof(s->leftover) - 1] = (uint8_t)(s->bits_hashed);
+	s->leftover[sizeof(s->leftover) - 2] = (uint8_t)(s->bits_hashed >> 8);
+	s->leftover[sizeof(s->leftover) - 3] = (uint8_t)(s->bits_hashed >> 16);
+	s->leftover[sizeof(s->leftover) - 4] = (uint8_t)(s->bits_hashed >> 24);
+	s->leftover[sizeof(s->leftover) - 5] = (uint8_t)(s->bits_hashed >> 32);
+	s->leftover[sizeof(s->leftover) - 6] = (uint8_t)(s->bits_hashed >> 40);
+	s->leftover[sizeof(s->leftover) - 7] = (uint8_t)(s->bits_hashed >> 48);
+	s->leftover[sizeof(s->leftover) - 8] = (uint8_t)(s->bits_hashed >> 56);
+
+	/* hash the padding and length */
+	compress(s->iv, s->leftover);
+
+	/* copy the iv out to digest */
+	for (i = 0; i < TC_SHA256_STATE_BLOCKS; ++i) {
+		unsigned int t = *((unsigned int *) &s->iv[i]);
+		*digest++ = (uint8_t)(t >> 24);
+		*digest++ = (uint8_t)(t >> 16);
+		*digest++ = (uint8_t)(t >> 8);
+		*digest++ = (uint8_t)(t);
+	}
+
+	/* destroy the current state */
+	_set(s, 0, sizeof(*s));
+
+	return TC_CRYPTO_SUCCESS;
+}
+
+/*
+ * Initializing SHA-256 Hash constant words K.
+ * These values correspond to the first 32 bits of the fractional parts of the
+ * cube roots of the first 64 primes between 2 and 311.
+ */
+static const unsigned int k256[64] = {
+	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
+	0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
+	0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+	0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
+	0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
+	0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+static inline unsigned int ROTR(unsigned int a, unsigned int n)
+{
+	return (((a) >> n) | ((a) << (32 - n)));
+}
+
+#define Sigma0(a)(ROTR((a), 2) ^ ROTR((a), 13) ^ ROTR((a), 22))
+#define Sigma1(a)(ROTR((a), 6) ^ ROTR((a), 11) ^ ROTR((a), 25))
+#define sigma0(a)(ROTR((a), 7) ^ ROTR((a), 18) ^ ((a) >> 3))
+#define sigma1(a)(ROTR((a), 17) ^ ROTR((a), 19) ^ ((a) >> 10))
+
+#define Ch(a, b, c)(((a) & (b)) ^ ((~(a)) & (c)))
+#define Maj(a, b, c)(((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c)))
+
+static inline unsigned int BigEndian(const uint8_t **c)
+{
+	unsigned int n = 0;
+
+	n = (((unsigned int)(*((*c)++))) << 24);
+	n |= ((unsigned int)(*((*c)++)) << 16);
+	n |= ((unsigned int)(*((*c)++)) << 8);
+	n |= ((unsigned int)(*((*c)++)));
+	return n;
+}
+
+static void compress(unsigned int *iv, const uint8_t *data)
+{
+	unsigned int a, b, c, d, e, f, g, h;
+	unsigned int s0, s1;
+	unsigned int t1, t2;
+	unsigned int work_space[16];
+	unsigned int n;
+	unsigned int i;
+
+	a = iv[0]; b = iv[1]; c = iv[2]; d = iv[3];
+	e = iv[4]; f = iv[5]; g = iv[6]; h = iv[7];
+
+	for (i = 0; i < 16; ++i) {
+		n = BigEndian(&data);
+		t1 = work_space[i] = n;
+		t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
+		t2 = Sigma0(a) + Maj(a, b, c);
+		h = g; g = f; f = e; e = d + t1;
+		d = c; c = b; b = a; a = t1 + t2;
+	}
+
+	for ( ; i < 64; ++i) {
+		s0 = work_space[(i+1)&0x0f];
+		s0 = sigma0(s0);
+		s1 = work_space[(i+14)&0x0f];
+		s1 = sigma1(s1);
+
+		t1 = work_space[i&0xf] += s0 + s1 + work_space[(i+9)&0xf];
+		t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
+		t2 = Sigma0(a) + Maj(a, b, c);
+		h = g; g = f; f = e; e = d + t1;
+		d = c; c = b; b = a; a = t1 + t2;
+	}
+
+	iv[0] += a; iv[1] += b; iv[2] += c; iv[3] += d;
+	iv[4] += e; iv[5] += f; iv[6] += g; iv[7] += h;
+}
diff --git a/tinycrypt/src/utils.c b/tinycrypt/src/utils.c
new file mode 100644
index 0000000..13cc495
--- /dev/null
+++ b/tinycrypt/src/utils.c
@@ -0,0 +1,74 @@
+/* utils.c - TinyCrypt platform-dependent run-time operations */
+
+/*
+ *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *    - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *
+ *    - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    - Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/utils.h>
+#include <tinycrypt/constants.h>
+
+#include <string.h>
+
+#define MASK_TWENTY_SEVEN 0x1b
+
+unsigned int _copy(uint8_t *to, unsigned int to_len,
+		   const uint8_t *from, unsigned int from_len)
+{
+	if (from_len <= to_len) {
+		(void)memcpy(to, from, from_len);
+		return from_len;
+	} else {
+		return TC_CRYPTO_FAIL;
+	}
+}
+
+void _set(void *to, uint8_t val, unsigned int len)
+{
+	(void)memset(to, val, len);
+}
+
+/*
+ * Doubles the value of a byte for values up to 127.
+ */
+uint8_t _double_byte(uint8_t a)
+{
+	return ((a<<1) ^ ((a>>7) * MASK_TWENTY_SEVEN));
+}
+
+int _compare(const uint8_t *a, const uint8_t *b, size_t size)
+{
+	const uint8_t *tempa = a;
+	const uint8_t *tempb = b;
+	uint8_t result = 0;
+
+	for (unsigned int i = 0; i < size; i++) {
+		result |= tempa[i] ^ tempb[i];
+	}
+	return result;
+}

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

[mynewt-nimble] 03/04: [wip] temporary fixes for controller build

Posted by an...@apache.org.
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 b27c0f4bda95f73ba83af0ff84665509f8af2f19
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Mon Dec 18 12:17:40 2017 +0100

    [wip] temporary fixes for controller build
    
    This should be fixed in upstream.
---
 nimble/controller/src/ble_ll.c      | 6 +++---
 nimble/controller/src/ble_ll_adv.c  | 1 -
 nimble/controller/src/ble_ll_conn.c | 1 -
 nimble/controller/src/ble_ll_scan.c | 1 -
 nimble/drivers/nrf52/src/ble_phy.c  | 2 +-
 5 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c
index 81fccc7..04c3239 100644
--- a/nimble/controller/src/ble_ll.c
+++ b/nimble/controller/src/ble_ll.c
@@ -1460,9 +1460,9 @@ ble_ll_init(void)
     lldata->ll_supp_features = features;
 
     /* Initialize the LL task */
-    os_task_init(&g_ble_ll_task, "ble_ll", ble_ll_task, NULL,
-                 MYNEWT_VAL(BLE_LL_PRIO), OS_WAIT_FOREVER, g_ble_ll_stack,
-                 BLE_LL_STACK_SIZE);
+//    os_task_init(&g_ble_ll_task, "ble_ll", ble_ll_task, NULL,
+//                 MYNEWT_VAL(BLE_LL_PRIO), OS_WAIT_FOREVER, g_ble_ll_stack,
+//                 BLE_LL_STACK_SIZE);
 
     rc = stats_init_and_reg(STATS_HDR(ble_ll_stats),
                             STATS_SIZE_INIT_PARMS(ble_ll_stats, STATS_SIZE_32),
diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c
index e362a32..5ab0899 100644
--- a/nimble/controller/src/ble_ll_adv.c
+++ b/nimble/controller/src/ble_ll_adv.c
@@ -38,7 +38,6 @@
 #include "controller/ble_ll_whitelist.h"
 #include "controller/ble_ll_resolv.h"
 #include "ble_ll_conn_priv.h"
-#include "hal/hal_gpio.h"
 
 /* XXX: TODO
  * 1) Need to look at advertising and scan request PDUs. Do I allocate these
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index 0901352..9d7fe15 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -40,7 +40,6 @@
 #include "controller/ble_phy.h"
 #include "controller/ble_hw.h"
 #include "ble_ll_conn_priv.h"
-#include "hal/hal_gpio.h"
 
 #if (BLETEST_THROUGHPUT_TEST == 1)
 extern void bletest_completed_pkt(uint16_t handle);
diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c
index c3ac7fe..adbd719 100644
--- a/nimble/controller/src/ble_ll_scan.c
+++ b/nimble/controller/src/ble_ll_scan.c
@@ -39,7 +39,6 @@
 #include "controller/ble_ll_resolv.h"
 #include "controller/ble_ll_xcvr.h"
 #include "ble_ll_conn_priv.h"
-#include "hal/hal_gpio.h"
 
 /*
  * XXX:
diff --git a/nimble/drivers/nrf52/src/ble_phy.c b/nimble/drivers/nrf52/src/ble_phy.c
index 690bbd7..d744250 100644
--- a/nimble/drivers/nrf52/src/ble_phy.c
+++ b/nimble/drivers/nrf52/src/ble_phy.c
@@ -24,7 +24,7 @@
 #include "os/os.h"
 #include "ble/xcvr.h"
 #include "bsp/cmsis_nvic.h"
-#include "hal/hal_gpio.h"
+// XXX #include "hal/hal_gpio.h"
 #include "nimble/ble.h"
 #include "nimble/nimble_opt.h"
 #include "controller/ble_phy.h"

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

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

Posted by an...@apache.org.
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 f1dba08467410f0e30e75b6cf8be7961fbddd86d
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>.