You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2015/11/30 21:56:24 UTC

[1/2] incubator-mynewt-tadpole git commit: Merge larva changes to tadpole.

Repository: incubator-mynewt-tadpole
Updated Branches:
  refs/heads/master ad160f542 -> 29ce5cdc6


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/src/os_mbuf.c
----------------------------------------------------------------------
diff --git a/libs/os/src/os_mbuf.c b/libs/os/src/os_mbuf.c
index 0b8bda1..b1be0fc 100644
--- a/libs/os/src/os_mbuf.c
+++ b/libs/os/src/os_mbuf.c
@@ -54,22 +54,84 @@
 
 #include <string.h>
 
+int 
+os_mqueue_init(struct os_mqueue *mq, void *arg)
+{
+    struct os_event *ev;
+
+    STAILQ_INIT(&mq->mq_head);
+    
+    ev = &mq->mq_ev;
+    memset(ev, 0, sizeof(*ev));
+    ev->ev_arg = arg;
+    ev->ev_type = OS_EVENT_T_MQUEUE_DATA;
+
+    return (0);
+}
+
+
+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);
+
+    m = OS_MBUF_PKTHDR_TO_MBUF(mp);
+
+    return (m);
+}
+
+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;
+
+    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);
+}
+
+
 /**
  * Initialize a pool of mbufs. 
  * 
  * @param omp     The mbuf pool to initialize 
  * @param mp      The memory pool that will hold this mbuf pool 
- * @param hdr_len The length of the header, in a header mbuf 
  * @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 hdr_len, uint16_t buf_len, uint16_t nbufs)
+os_mbuf_pool_init(struct os_mbuf_pool *omp, struct os_mempool *mp, uint16_t buf_len, 
+        uint16_t nbufs)
 {
-    omp->omp_hdr_len = hdr_len;
     omp->omp_databuf_len = buf_len - sizeof(struct os_mbuf);
     omp->omp_mbuf_count = nbufs;
     omp->omp_pool = mp;
@@ -101,6 +163,7 @@ os_mbuf_get(struct os_mbuf_pool *omp, uint16_t leadingspace)
     om->om_flags = 0;
     om->om_len = 0;
     om->om_data = (&om->om_databuf[0] + leadingspace);
+    om->om_omp = omp;
 
     return (om);
 err:
@@ -109,14 +172,20 @@ err:
 
 /* Allocate a new packet header mbuf out of the os_mbuf_pool */ 
 struct os_mbuf *
-os_mbuf_get_pkthdr(struct os_mbuf_pool *omp)
+os_mbuf_get_pkthdr(struct os_mbuf_pool *omp, uint8_t extra_pkthdr_len)
 {
+    struct os_mbuf_pkthdr *pkthdr;
     struct os_mbuf *om;
 
     om = os_mbuf_get(omp, 0);
     if (om) {
-        om->om_flags |= OS_MBUF_F_MASK(OS_MBUF_F_PKTHDR);
-        om->om_data += omp->omp_hdr_len + sizeof(struct os_mbuf_pkthdr);
+        om->om_pkthdr_len = extra_pkthdr_len + sizeof(struct os_mbuf_pkthdr);
+        om->om_data += extra_pkthdr_len + sizeof(struct os_mbuf_pkthdr);
+
+        pkthdr = OS_MBUF_PKTHDR(om);
+        pkthdr->omp_len = 0;
+        pkthdr->omp_flags = 0;
+        STAILQ_NEXT(pkthdr, omp_next) = NULL;
     }
 
     return om;
@@ -131,11 +200,11 @@ os_mbuf_get_pkthdr(struct os_mbuf_pool *omp)
  * @return 0 on success, -1 on failure 
  */
 int 
-os_mbuf_free(struct os_mbuf_pool *omp, struct os_mbuf *om) 
+os_mbuf_free(struct os_mbuf *om) 
 {
     int rc;
 
-    rc = os_memblock_put(omp->omp_pool, om);
+    rc = os_memblock_put(om->om_omp->omp_pool, om);
     if (rc != 0) {
         goto err;
     }
@@ -154,7 +223,7 @@ err:
  * @return 0 on success, -1 on failure 
  */
 int 
-os_mbuf_free_chain(struct os_mbuf_pool *omp, struct os_mbuf *om)
+os_mbuf_free_chain(struct os_mbuf *om)
 {
     struct os_mbuf *next;
     int rc;
@@ -162,7 +231,7 @@ os_mbuf_free_chain(struct os_mbuf_pool *omp, struct os_mbuf *om)
     while (om != NULL) {
         next = SLIST_NEXT(om, om_next);
 
-        rc = os_mbuf_free(omp, om);
+        rc = os_mbuf_free(om);
         if (rc != 0) {
             goto err;
         }
@@ -183,11 +252,10 @@ err:
  * @param old_buf The old buffer to copy the packet header from
  */
 static inline void 
-_os_mbuf_copypkthdr(struct os_mbuf_pool *omp, struct os_mbuf *new_buf, 
-        struct os_mbuf *old_buf)
+_os_mbuf_copypkthdr(struct os_mbuf *new_buf, struct os_mbuf *old_buf)
 {
     memcpy(&new_buf->om_databuf[0], &old_buf->om_databuf[0], 
-            sizeof(struct os_mbuf_pkthdr) + omp->omp_hdr_len);
+           old_buf->om_pkthdr_len);
 }
 
 /** 
@@ -201,20 +269,22 @@ _os_mbuf_copypkthdr(struct os_mbuf_pool *omp, struct os_mbuf *new_buf,
  * @return 0 on success, and an error code on failure 
  */
 int 
-os_mbuf_append(struct os_mbuf_pool *omp, struct os_mbuf *om, void *data,  
-        uint16_t len)
+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 (omp == NULL || om == NULL) {
+    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) {
@@ -222,7 +292,7 @@ os_mbuf_append(struct os_mbuf_pool *omp, struct os_mbuf *om, void *data,
     }
 
     remainder = len;
-    space = OS_MBUF_TRAILINGSPACE(omp, last);
+    space = OS_MBUF_TRAILINGSPACE(last);
 
     /* If room in current mbuf, copy the first part of the data into the 
      * remaining space in that mbuf.
@@ -232,7 +302,7 @@ os_mbuf_append(struct os_mbuf_pool *omp, struct os_mbuf *om, void *data,
             space = remainder;
         }
 
-        memcpy(OS_MBUF_DATA(last, void *), data, space);
+        memcpy(OS_MBUF_DATA(last, void *) + last->om_len , data, space);
 
         last->om_len += space;
         data += space;
@@ -243,7 +313,7 @@ os_mbuf_append(struct os_mbuf_pool *omp, struct os_mbuf *om, void *data,
      * data into it, until data is exhausted.
      */
     while (remainder > 0) {
-        new = os_mbuf_get(omp, OS_MBUF_START_OFF(omp)); 
+        new = os_mbuf_get(omp, 0); 
         if (!new) {
             break;
         }
@@ -282,32 +352,35 @@ err:
  * @return A pointer to the new chain of mbufs 
  */
 struct os_mbuf *
-os_mbuf_dup(struct os_mbuf_pool *omp, struct os_mbuf *om)
+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(omp, om)); 
+                    OS_MBUF_LEADINGSPACE(om)); 
             if (!SLIST_NEXT(copy, om_next)) {
-                os_mbuf_free_chain(omp, head);
+                os_mbuf_free_chain(head);
                 goto err;
             }
 
             copy = SLIST_NEXT(copy, om_next);
         } else {
-            head = os_mbuf_get(omp, OS_MBUF_LEADINGSPACE(omp, om));
+            head = os_mbuf_get(omp, OS_MBUF_LEADINGSPACE(om));
             if (!head) {
                 goto err;
             }
 
-            if (om->om_flags & OS_MBUF_F_MASK(OS_MBUF_F_PKTHDR)) {
-                _os_mbuf_copypkthdr(omp, head, om);
+            if (OS_MBUF_IS_PKTHDR(om)) {
+                _os_mbuf_copypkthdr(head, om);
             }
             copy = head;
         }
@@ -322,6 +395,440 @@ 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(struct os_mbuf *om, int off, int *out_off)
+{
+    struct os_mbuf *next;
+
+    while (1) {
+        if (om == NULL) {
+            return NULL;
+        }
+
+        next = SLIST_NEXT(om, om_next);
+
+        if (om->om_len > off ||
+            (om->om_len == off && next == NULL)) {
+
+            *out_off = off;
+            return om;
+        }
+
+        off -= om->om_len;
+        om = next;
+    }
+}
+
+/*
+ * Copy data from an mbuf chain starting "off" bytes from the beginning,
+ * continuing for "len" bytes, into the indicated buffer.
+ *
+ * @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;
+
+    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);
+}
+
+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;
+ *                              -1 if the mbuf is too short.
+ */
+int
+os_mbuf_memcmp(const struct os_mbuf *om, int off, const void *data, int len)
+{
+    int chunk_sz;
+    int data_off;
+    int om_off;
+    int rc;
+
+    if (len <= 0) {
+        return 0;
+    }
+
+    data_off = 0;
+    om = os_mbuf_off((struct os_mbuf *)om, off, &om_off);
+    while (1) {
+        if (om == NULL) {
+            return -1;
+        }
+
+        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 -1;
+        }
+    }
+}
+
+/**
+ * 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;
+}
+
+/**
+ * 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;
+    int copylen;
+    int cur_off;
+    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;
+    }
+
+    /* 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;
+}
+
 #if 0
 
 /**
@@ -341,16 +848,19 @@ err:
  * @return The contiguous mbuf chain on success, NULL on failure.
  */
 struct os_mbuf *
-os_mbuf_pullup(struct os_mbuf_pool *omp, struct os_mbuf *om, uint16_t len)
+os_mbuf_pullup(struct os_mbuf *om, uint16_t len)
 {
+    struct os_mbuf_pool *omp;
     struct os_mbuf *newm;
 
+    omp = om->om_omp;
+
     if (len > omp->omp_databuf_len) {
         goto err;
     }
 
     /* Is 'n' bytes already contiguous? */
-    if (((uint8_t *) &om->om_databuf[0] + OS_MBUF_END_OFF(omp)) - 
+    if (((uint8_t *) &om->om_databuf[0] + omp->omp_databuf_len) - 
             OS_MBUF_DATA(om, uint8_t *) >= len) {
         newm = om;
         goto done;
@@ -359,7 +869,7 @@ os_mbuf_pullup(struct os_mbuf_pool *omp, struct os_mbuf *om, uint16_t len)
     /* Nope, OK. Allocate a new buffer, and then go through and copy 'n' 
      * bytes into that buffer.
      */
-    newm = os_mbuf_get(omp, OS_MBUF_START_OFF(omp));
+    newm = os_mbuf_get(omp, 0);
     if (!newm) {
         goto err;
     }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/src/os_sched.c
----------------------------------------------------------------------
diff --git a/libs/os/src/os_sched.c b/libs/os/src/os_sched.c
index 240bc62..944f0f6 100644
--- a/libs/os/src/os_sched.c
+++ b/libs/os/src/os_sched.c
@@ -25,6 +25,9 @@ TAILQ_HEAD(, os_task) 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
  *  
@@ -68,6 +71,57 @@ err:
 }
 
 /**
+ * Walk all the active tasks currently being scheduled.
+ *
+ * @param walk_func The walk function to call for each task
+ * @param arg       The argument to pass the walk function
+ *
+ * @return 0 on success, < 0 on abort.
+ */
+int
+os_sched_walk(os_sched_walk_func_t walk_func, void *arg)
+{
+    struct os_task *t;
+    os_sr_t sr;
+    int rc;
+
+    /* Go through tasks and fill out the info blocks
+     */
+    OS_ENTER_CRITICAL(sr);
+    TAILQ_FOREACH(t, &g_os_run_list, t_os_list) {
+        rc = walk_func(t, arg);
+        if (rc != 0) {
+            goto done;
+        }
+    }
+
+    TAILQ_FOREACH(t, &g_os_sleep_list, t_os_list) {
+        rc = walk_func(t, arg);
+        if (rc != 0) {
+            goto done;
+        }
+    }
+
+done:
+    OS_EXIT_CRITICAL(sr);
+
+    return (rc);
+}
+
+void
+os_sched_ctx_sw_hook(struct os_task *next_t)
+{
+    if (g_current_task == next_t) {
+        return;
+    }
+
+    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 
@@ -118,7 +172,7 @@ os_sched(struct os_task *next_t, int isr)
         next_t = os_sched_next_task();
     }
 
-    if (next_t != os_sched_get_current_task()) {
+    if (next_t != g_current_task) {
         OS_EXIT_CRITICAL(sr);
         if (isr) {
             os_arch_ctx_sw_isr(next_t);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/src/os_task.c
----------------------------------------------------------------------
diff --git a/libs/os/src/os_task.c b/libs/os/src/os_task.c
index f9da560..950d54f 100644
--- a/libs/os/src/os_task.c
+++ b/libs/os/src/os_task.c
@@ -45,6 +45,12 @@ os_task_next_id(void)
     return (rc);
 }
 
+uint8_t 
+os_task_count(void)
+{
+    return (g_task_id);
+}
+
 int 
 os_task_sanity_checkin(struct os_task *t)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/src/os_time.c
----------------------------------------------------------------------
diff --git a/libs/os/src/os_time.c b/libs/os/src/os_time.c
index cc2e819..9613159 100644
--- a/libs/os/src/os_time.c
+++ b/libs/os/src/os_time.c
@@ -17,7 +17,7 @@
 #include "os/os.h"
 #include "os/queue.h"
 
-static os_time_t g_os_time = 0;
+os_time_t g_os_time = 0;
 
 os_time_t  
 os_time_get(void)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/src/test/mbuf_test.c
----------------------------------------------------------------------
diff --git a/libs/os/src/test/mbuf_test.c b/libs/os/src/test/mbuf_test.c
index 6d98452..8652494 100644
--- a/libs/os/src/test/mbuf_test.c
+++ b/libs/os/src/test/mbuf_test.c
@@ -38,7 +38,7 @@ os_mbuf_test_setup(void)
             MBUF_TEST_POOL_BUF_SIZE, &os_mbuf_membuf[0], "mbuf_pool");
     TEST_ASSERT_FATAL(rc == 0, "Error creating memory pool %d", rc);
 
-    rc = os_mbuf_pool_init(&os_mbuf_pool, &os_mbuf_mempool, 0, 
+    rc = os_mbuf_pool_init(&os_mbuf_pool, &os_mbuf_mempool,
             MBUF_TEST_POOL_BUF_SIZE, MBUF_TEST_POOL_BUF_COUNT);
     TEST_ASSERT_FATAL(rc == 0, "Error creating mbuf pool %d", rc);
 }
@@ -53,7 +53,7 @@ TEST_CASE(os_mbuf_test_case_1)
     m = os_mbuf_get(&os_mbuf_pool, 0);
     TEST_ASSERT_FATAL(m != NULL, "Error allocating mbuf");
 
-    rc = os_mbuf_free(&os_mbuf_pool, m);
+    rc = os_mbuf_free(m);
     TEST_ASSERT_FATAL(rc == 0, "Error free'ing mbuf %d", rc);
 }
 
@@ -68,14 +68,14 @@ TEST_CASE(os_mbuf_test_case_2)
     m = os_mbuf_get(&os_mbuf_pool, 0);
     TEST_ASSERT_FATAL(m != NULL, "Error allocating mbuf");
 
-    dup = os_mbuf_dup(&os_mbuf_pool, m);
+    dup = os_mbuf_dup(m);
     TEST_ASSERT_FATAL(dup != NULL, "NULL mbuf returned from dup");
     TEST_ASSERT_FATAL(dup != m, "duplicate matches original.");
 
-    rc = os_mbuf_free(&os_mbuf_pool, m);
+    rc = os_mbuf_free(m);
     TEST_ASSERT_FATAL(rc == 0, "Error free'ing mbuf m %d", rc);
     
-    rc = os_mbuf_free(&os_mbuf_pool, dup);
+    rc = os_mbuf_free(dup);
     TEST_ASSERT_FATAL(rc == 0, "Error free'ing mbuf dup %d", rc);
 
     m = os_mbuf_get(&os_mbuf_pool, 0);
@@ -86,16 +86,16 @@ TEST_CASE(os_mbuf_test_case_2)
 
     SLIST_NEXT(m, om_next) = m2; 
 
-    dup = os_mbuf_dup(&os_mbuf_pool, m);
+    dup = os_mbuf_dup(m);
     TEST_ASSERT_FATAL(dup != NULL, "NULL mbuf returned from dup");
     TEST_ASSERT_FATAL(dup != m, "Duplicate matches original");
     TEST_ASSERT_FATAL(SLIST_NEXT(dup, om_next) != NULL, 
             "NULL chained element, duplicate should match original");
 
-    rc = os_mbuf_free_chain(&os_mbuf_pool, m);
+    rc = os_mbuf_free_chain(m);
     TEST_ASSERT_FATAL(rc == 0, "Cannot free mbuf chain %d", rc);
 
-    rc = os_mbuf_free_chain(&os_mbuf_pool, dup);
+    rc = os_mbuf_free_chain(dup);
     TEST_ASSERT_FATAL(rc == 0, "Cannot free mbuf chain %d", rc);
 }
 
@@ -109,7 +109,7 @@ TEST_CASE(os_mbuf_test_case_3)
     m = os_mbuf_get(&os_mbuf_pool, 0);
     TEST_ASSERT_FATAL(m != NULL, "Error allocating mbuf");
 
-    rc = os_mbuf_append(&os_mbuf_pool, m, databuf, sizeof(databuf));
+    rc = os_mbuf_append(m, databuf, sizeof(databuf));
     TEST_ASSERT_FATAL(rc == 0, "Cannot add %d bytes to mbuf", 
             sizeof(databuf));
     TEST_ASSERT_FATAL(m->om_len == sizeof(databuf), 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/testutil/src/suite.c
----------------------------------------------------------------------
diff --git a/libs/testutil/src/suite.c b/libs/testutil/src/suite.c
index b6decb0..a6f2126 100644
--- a/libs/testutil/src/suite.c
+++ b/libs/testutil/src/suite.c
@@ -18,8 +18,8 @@
 #include "testutil/testutil.h"
 #include "testutil_priv.h"
 
-const char *tu_suite_name;
-int tu_suite_failed;
+const char *tu_suite_name = 0;
+int tu_suite_failed = 0;
 
 static void
 tu_suite_set_name(const char *name)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/egg.yml
----------------------------------------------------------------------
diff --git a/libs/util/egg.yml b/libs/util/egg.yml
new file mode 100644
index 0000000..3faef1b
--- /dev/null
+++ b/libs/util/egg.yml
@@ -0,0 +1,13 @@
+egg.name: libs/util
+egg.vers: 0.1
+egg.deps:
+    - hw/hal
+    - libs/os
+    - libs/testutil
+egg.deps.SHELL:
+    - libs/console/full
+    - libs/shell
+egg.cflags.SHELL: -DSHELL_PRESENT
+egg.deps.NFFS:
+    - libs/nffs
+egg.cflags.NFFS: -DNFFS_PRESENT

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/include/util/cbmem.h
----------------------------------------------------------------------
diff --git a/libs/util/include/util/cbmem.h b/libs/util/include/util/cbmem.h
new file mode 100644
index 0000000..1a0fa34
--- /dev/null
+++ b/libs/util/include/util/cbmem.h
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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_CBMEM_H__ 
+#define __UTIL_CBMEM_H__
+
+#include <os/os.h>
+
+struct cbmem_entry_hdr {
+    uint16_t ceh_len;
+    uint16_t ceh_flags;
+};
+
+struct cbmem {
+    struct os_mutex c_lock;
+
+    struct cbmem_entry_hdr *c_entry_start;
+    struct cbmem_entry_hdr *c_entry_end;
+    uint8_t *c_buf;
+    uint8_t *c_buf_end;
+    uint8_t *c_buf_cur_end;
+};
+
+struct cbmem_iter {
+    struct cbmem_entry_hdr *ci_start;
+    struct cbmem_entry_hdr *ci_cur;
+    struct cbmem_entry_hdr *ci_end;
+};
+
+#define CBMEM_ENTRY_SIZE(__p) (sizeof(struct cbmem_entry_hdr) \
+        + ((struct cbmem_entry_hdr *) (__p))->ceh_len)
+#define CBMEM_ENTRY_NEXT(__p) ((struct cbmem_entry_hdr *) \
+        ((uint8_t *) (__p) + CBMEM_ENTRY_SIZE(__p)))
+
+typedef int (*cbmem_walk_func_t)(struct cbmem *, struct cbmem_entry_hdr *, 
+        void *arg);
+
+int cbmem_lock_acquire(struct cbmem *cbmem);
+int cbmem_lock_release(struct cbmem *cbmem);
+int cbmem_init(struct cbmem *cbmem, void *buf, uint32_t buf_len);
+int cbmem_append(struct cbmem *cbmem, void *data, uint16_t len);
+void cbmem_iter_start(struct cbmem *cbmem, struct cbmem_iter *iter);
+struct cbmem_entry_hdr *cbmem_iter_next(struct cbmem *cbmem, 
+        struct cbmem_iter *iter);
+int cbmem_read(struct cbmem *cbmem, struct cbmem_entry_hdr *hdr, void *buf, 
+        uint16_t off, uint16_t len);
+int cbmem_walk(struct cbmem *cbmem, cbmem_walk_func_t walk_func, void *arg);
+
+int cbmem_flush(struct cbmem *);
+
+#endif /* __UTIL_CBMEM_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/include/util/flash_map.h
----------------------------------------------------------------------
diff --git a/libs/util/include/util/flash_map.h b/libs/util/include/util/flash_map.h
new file mode 100644
index 0000000..3b77c86
--- /dev/null
+++ b/libs/util/include/util/flash_map.h
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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_FLASH_MAP_
+#define H_UTIL_FLASH_MAP_
+
+/**
+ *
+ * Provides abstraction of flash regions for type of use.
+ * I.e. dude where's my image?
+ *
+ * System will contain a map which contains flash areas. Every
+ * region will contain flash identifier, offset within flash and length.
+ *
+ * 1. This system map could be in a file within filesystem (Initializer
+ * must know/figure out where the filesystem is at).
+ * 2. Map could be at fixed location for project (compiled to code)
+ * 3. Map could be at specific place in flash (put in place at mfg time).
+ *
+ * Note that the map you use must be valid for BSP it's for,
+ * match the linker scripts when platform executes from flash,
+ * and match the target offset specified in download script.
+ */
+#include <inttypes.h>
+
+struct flash_area {
+    uint8_t fa_flash_id;
+    uint8_t _pad[3];
+    uint32_t fa_off;
+    uint32_t fa_size;
+};
+
+/*
+ * Flash area types
+ */
+#define FLASH_AREA_BOOTLOADER           0
+#define FLASH_AREA_IMAGE_0              1
+#define FLASH_AREA_IMAGE_1              2
+#define FLASH_AREA_IMAGE_SCRATCH        3
+#define FLASH_AREA_NFFS                 4
+
+/*
+ * Initializes flash map. Memory will be referenced by flash_map code
+ * from this on.
+ */
+void flash_area_init(const struct flash_area *map, int map_entries);
+
+/*
+ * Start using flash area.
+ */
+int flash_area_open(int idx, const struct flash_area **);
+
+void flash_area_close(const struct flash_area *);
+
+/*
+ * Read/write/erase. Offset is relative from beginning of flash area.
+ */
+int flash_area_read(const struct flash_area *, uint32_t off, void *dst,
+  uint32_t len);
+int flash_area_write(const struct flash_area *, uint32_t off, void *src,
+  uint32_t len);
+int flash_area_erase(const struct flash_area *, uint32_t off, uint32_t len);
+
+/*
+ * Given flash map index, return info about sectors within the area.
+ */
+int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret);
+
+/*
+ * Given flash map index, return sector info in NFFS area desc format.
+ */
+struct nffs_area_desc;
+int flash_area_to_nffs_desc(int idx, int *cnt, struct nffs_area_desc *nad);
+
+#endif /* H_UTIL_FLASH_MAP_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/include/util/log.h
----------------------------------------------------------------------
diff --git a/libs/util/include/util/log.h b/libs/util/include/util/log.h
new file mode 100644
index 0000000..b1b64d7
--- /dev/null
+++ b/libs/util/include/util/log.h
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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_LOG_H__ 
+#define __UTIL_LOG_H__
+
+#include "util/cbmem.h"
+#include <os/queue.h>
+
+struct util_log;
+
+typedef int (*util_log_walk_func_t)(struct util_log *, void *arg, void *offset, 
+        uint16_t len);
+
+typedef int (*ulh_read_func_t)(struct util_log *, void *dptr, void *buf, 
+        uint16_t offset, uint16_t len);
+typedef int (*ulh_append_func_t)(struct util_log *, void *buf, int len);
+typedef int (*ulh_walk_func_t)(struct util_log *, 
+        util_log_walk_func_t walk_func, void *arg);
+typedef int (*ulh_flush_func_t)(struct util_log *);
+
+struct ul_handler {
+    ulh_read_func_t ulh_read;
+    ulh_append_func_t ulh_append;
+    ulh_walk_func_t ulh_walk;
+    ulh_flush_func_t ulh_flush;
+    void *ulh_arg;
+};
+
+struct ul_entry_hdr {
+    int64_t ue_ts;
+}; 
+
+struct util_log {
+    char *ul_name;
+    struct ul_handler *ul_ulh;
+    STAILQ_ENTRY(util_log) ul_next;
+};
+
+int util_log_cbmem_handler_init(struct ul_handler *, struct cbmem *);
+int util_log_register(char *name, struct util_log *log, struct ul_handler *);
+int util_log_append(struct util_log *log, uint8_t *data, uint16_t len);
+int util_log_read(struct util_log *log, void *dptr, void *buf, uint16_t off, 
+        uint16_t len);
+int util_log_walk(struct util_log *log, util_log_walk_func_t walk_func, 
+        void *arg);
+int util_log_flush(struct util_log *log);
+
+#endif /* __UTIL_LOG_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/include/util/stats.h
----------------------------------------------------------------------
diff --git a/libs/util/include/util/stats.h b/libs/util/include/util/stats.h
new file mode 100644
index 0000000..f35e0c0
--- /dev/null
+++ b/libs/util/include/util/stats.h
@@ -0,0 +1,108 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <os/queue.h>
+#include <stdint.h>
+
+struct stats_name_map {
+    void *snm_off;
+    char *snm_name;
+};
+
+struct stats_hdr {
+    char *s_name;
+    uint8_t s_size;
+    uint8_t s_cnt;
+    uint16_t s_pad1;
+#ifdef STATS_NAME_ENABLE
+    struct stats_name_map *s_map;
+    int s_map_cnt;
+#endif
+    STAILQ_ENTRY(stats_hdr) s_next;
+};
+
+
+#define STATS_SECT_START(__name)           \
+struct stats_ ## __name {                  \
+    struct stats_hdr s_hdr;
+
+
+#define STATS_SECT_END(__name)           \
+} g_stats_ ## __name;
+
+#define STATS_SECT_NAME(__name) \
+    g_stats_ ## __name
+
+#define STATS_HDR(__name) ((struct stats_hdr *) &STATS_SECT_NAME(__name))
+
+#define STATS_SECT_VAR(__var) \
+    s##__var 
+
+#define STATS_SIZE_16 (sizeof(uint16_t))
+#define STATS_SIZE_32 (sizeof(uint32_t))
+#define STATS_SIZE_64 (sizeof(uint64_t))
+
+#define STATS_SECT_ENTRY(__var) uint32_t STATS_SECT_VAR(__var);
+#define STATS_SECT_ENTRY16(__var) uint16_t STATS_SECT_VAR(__var);
+#define STATS_SECT_ENTRY32(__var) uint32_t STATS_SECT_VAR(__var);
+#define STATS_SECT_ENTRY64(__var) uint64_t STATS_SECT_VAR(__var);
+
+#define STATS_SIZE_INIT_PARMS(__name, __size)                              \
+    __size,                                                                \
+    ((sizeof(STATS_SECT_NAME(__name)) - sizeof(struct stats_hdr)) / __size)
+
+
+#define STATS_INC(__name, __var) \
+    (STATS_SECT_NAME(__name).STATS_SECT_VAR(__var)++)
+
+#define STATS_INCN(__name, __var, __n) \
+    (STATS_SECT_NAME(__name).STATS_SECT_VAR(__var) += (__n))
+
+#ifdef STATS_NAME_ENABLE
+
+#define STATS_NAME_MAP_NAME(__name) g_stats_map_ ## __name
+
+#define STATS_NAME_START(__name)                      \
+struct stats_name_map STATS_NAME_MAP_NAME(__name)[] = {
+
+#define STATS_NAME(__name, __entry)                   \
+    { &STATS_SECT_NAME(__name).STATS_SECT_VAR(__entry), #__entry },
+
+#define STATS_NAME_END(__name)                        \
+};
+
+#define STATS_NAME_INIT_PARMS(__name)                                    \
+    &(STATS_NAME_MAP_NAME(__name)[0]),                                   \
+    (sizeof(STATS_NAME_MAP_NAME(__name)) / sizeof(struct stats_name_map))
+
+#else /* STATS_NAME_ENABLE */
+
+#define STATS_NAME_START(__name)
+#define STATS_NAME(__name, __entry)
+#define STATS_NAME_END(__name)
+#define STATS_NAME_INIT_PARMS(__name) NULL, 0
+
+#endif /* STATS_NAME_ENABLE */
+
+int stats_module_init(void);
+int stats_init(struct stats_hdr *shdr, uint8_t size, uint8_t cnt, 
+    struct stats_name_map *map, uint8_t map_cnt);
+int stats_register(char *name, struct stats_hdr *shdr);
+struct stats_hdr *stats_find(char *name);
+
+#endif /* __UTIL_STATS_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/include/util/tpq.h
----------------------------------------------------------------------
diff --git a/libs/util/include/util/tpq.h b/libs/util/include/util/tpq.h
new file mode 100644
index 0000000..e0a536b
--- /dev/null
+++ b/libs/util/include/util/tpq.h
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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_TPQ_H__ 
+#define __UTIL_TPQ_H__
+
+#include <os/queue.h>
+#include <os/os_eventq.h>
+
+/* A task packet queue element */
+struct tpq_elem {
+    STAILQ_ENTRY(tpq_elem) tpq_next;
+};
+
+/* The task packet queue object */
+struct tpq
+{
+    STAILQ_HEAD(, tpq_elem) tpq_head;
+    struct os_event tpq_ev;
+};
+
+/**
+ * Put an element on a task packet queue and post an event to an event queue. 
+ * 
+ * @param evq   Pointer to event queue
+ * @param tpq   Pointer to task packet queue
+ * @param elem  Pointer to element to enqueue
+ */
+void tpq_put(struct os_eventq *evq, struct tpq *tpq, struct tpq_elem *elem);
+
+/**
+ * Retrieve an element from a task packet queue. This removes the element at 
+ * the head of the queue. 
+ * 
+ * @param head 
+ * 
+ * @return struct tpq_elem* 
+ */
+struct tpq_elem *tpq_get(struct tpq *tpq);
+
+/**
+ * Initialize a task packet queue 
+ * 
+ * @param tpq Pointer to task packet queue
+ * @param ev_type Type of event.
+ * @param ev_arg Argument of event
+ * 
+ * @return int 
+ */
+void tpq_init(struct tpq *tpq, uint8_t ev_type, void *ev_arg);
+
+#endif /* __UTIL_TPQ_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/include/util/util.h
----------------------------------------------------------------------
diff --git a/libs/util/include/util/util.h b/libs/util/include/util/util.h
new file mode 100644
index 0000000..110af87
--- /dev/null
+++ b/libs/util/include/util/util.h
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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_H__ 
+#define __UTIL_H__
+
+#endif /* __UTIL_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/src/cbmem.c
----------------------------------------------------------------------
diff --git a/libs/util/src/cbmem.c b/libs/util/src/cbmem.c
new file mode 100644
index 0000000..84d161f
--- /dev/null
+++ b/libs/util/src/cbmem.c
@@ -0,0 +1,269 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 "util/cbmem.h" 
+
+
+int 
+cbmem_init(struct cbmem *cbmem, void *buf, uint32_t buf_len)
+{
+    os_mutex_init(&cbmem->c_lock);
+
+    memset(cbmem, 0, sizeof(*cbmem));
+    cbmem->c_buf = buf;
+    cbmem->c_buf_end = buf + buf_len;
+
+    return (0);
+}
+
+int 
+cbmem_lock_acquire(struct cbmem *cbmem) 
+{
+    int rc;
+
+    if (!os_started()) {
+        return (0);
+    }
+
+    rc = os_mutex_pend(&cbmem->c_lock, OS_WAIT_FOREVER);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+int 
+cbmem_lock_release(struct cbmem *cbmem)
+{
+    int rc;
+
+    if (!os_started()) {
+        return (0);
+    }
+
+    rc = os_mutex_release(&cbmem->c_lock);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+
+int 
+cbmem_append(struct cbmem *cbmem, void *data, uint16_t len)
+{
+    struct cbmem_entry_hdr *dst;
+    uint8_t *start;
+    uint8_t *end;
+    int rc;
+
+    rc = cbmem_lock_acquire(cbmem);
+    if (rc != 0) {
+        goto err;
+    }
+
+    if (cbmem->c_entry_end) {
+        dst = CBMEM_ENTRY_NEXT(cbmem->c_entry_end);
+    } else {
+        dst = (struct cbmem_entry_hdr *) cbmem->c_buf;
+    }
+    end = (uint8_t *) dst + len;
+
+    /* If this item would take us past the end of this buffer, then adjust 
+     * the item to the beginning of the buffer.
+     */
+    if (end > cbmem->c_buf_end) {
+        cbmem->c_buf_cur_end = (uint8_t *) dst;
+        dst = (struct cbmem_entry_hdr *) cbmem->c_buf;
+        end = (uint8_t *) dst + len;
+        if ((uint8_t *) cbmem->c_entry_start >= cbmem->c_buf_cur_end) {
+            cbmem->c_entry_start = (struct cbmem_entry_hdr *) cbmem->c_buf;
+        }
+    }
+
+    /* If the destination is prior to the start, and would overrwrite the 
+     * start of the buffer, move start forward until you don't overwrite it
+     * anymore.
+     */
+    start = (uint8_t *) cbmem->c_entry_start;
+    if (start && (uint8_t *) dst < start + CBMEM_ENTRY_SIZE(start) && 
+            end > start) {
+        while (start < end) {
+            start = (uint8_t *) CBMEM_ENTRY_NEXT(start);
+            if (start == cbmem->c_buf_cur_end) {
+                start = cbmem->c_buf;
+                break;
+            }
+        }
+        cbmem->c_entry_start = (struct cbmem_entry_hdr *) start;
+    }
+
+    /* Copy the entry into the log 
+     */
+    dst->ceh_len = len;
+    memcpy((uint8_t *) dst + sizeof(*dst), data, len);
+
+    cbmem->c_entry_end = dst;
+    if (!cbmem->c_entry_start) {
+        cbmem->c_entry_start = dst;
+    }
+
+    rc = cbmem_lock_release(cbmem);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (-1);
+}
+
+void 
+cbmem_iter_start(struct cbmem *cbmem, struct cbmem_iter *iter)
+{
+    iter->ci_start = cbmem->c_entry_start;
+    iter->ci_cur = cbmem->c_entry_start;
+    iter->ci_end = cbmem->c_entry_end;
+}
+
+struct cbmem_entry_hdr *
+cbmem_iter_next(struct cbmem *cbmem, struct cbmem_iter *iter)
+{
+    struct cbmem_entry_hdr *hdr;
+
+    if (iter->ci_start > iter->ci_end) {
+        hdr = iter->ci_cur;
+        iter->ci_cur = CBMEM_ENTRY_NEXT(iter->ci_cur);
+
+        if ((uint8_t *) iter->ci_cur == cbmem->c_buf_cur_end) {
+            iter->ci_cur = (struct cbmem_entry_hdr *) cbmem->c_buf;
+            iter->ci_start = (struct cbmem_entry_hdr *) cbmem->c_buf;
+        }
+    } else {
+        hdr = iter->ci_cur;
+        if (hdr == CBMEM_ENTRY_NEXT(iter->ci_end)) {
+            hdr = NULL;
+        } else {
+            iter->ci_cur = CBMEM_ENTRY_NEXT(iter->ci_cur);
+        }
+    }
+
+    return (hdr);
+}
+
+int
+cbmem_flush(struct cbmem *cbmem)
+{
+    int rc;
+
+    rc = cbmem_lock_acquire(cbmem);
+    if (rc != 0) {
+        goto err;
+    }
+
+    cbmem->c_entry_start = NULL;
+    cbmem->c_entry_end = NULL;
+    cbmem->c_buf_cur_end = NULL;
+
+    rc = cbmem_lock_release(cbmem);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+int 
+cbmem_read(struct cbmem *cbmem, struct cbmem_entry_hdr *hdr, void *buf, 
+        uint16_t off, uint16_t len)
+{
+    int rc;
+
+    rc = cbmem_lock_acquire(cbmem);
+    if (rc != 0) {
+        goto err;
+    }
+
+    /* Only read the maximum number of bytes, if we exceed that, 
+     * truncate the read.
+     */
+    if (off + len > hdr->ceh_len) {
+        len = hdr->ceh_len - off;
+    }
+
+    if (off > hdr->ceh_len) {
+        rc = -1;
+        cbmem_lock_release(cbmem);
+        goto err;
+    }
+
+    memcpy(buf, (uint8_t *) hdr + sizeof(*hdr) + off, len);
+
+    rc = cbmem_lock_release(cbmem);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (len);
+err:
+    return (-1);
+}
+
+int 
+cbmem_walk(struct cbmem *cbmem, cbmem_walk_func_t walk_func, void *arg)
+{
+    struct cbmem_entry_hdr *hdr;
+    struct cbmem_iter iter;
+    int rc;
+
+    rc = cbmem_lock_acquire(cbmem);
+    if (rc != 0) {
+        goto err;
+    }
+
+    cbmem_iter_start(cbmem, &iter);
+    while (1) {
+        hdr = cbmem_iter_next(cbmem, &iter);
+        if (hdr == NULL) {
+            break;
+        }
+
+        rc = walk_func(cbmem, hdr, arg);
+        if (rc == 1) {
+            break;
+        }
+    }
+
+    rc = cbmem_lock_release(cbmem);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/src/flash_map.c
----------------------------------------------------------------------
diff --git a/libs/util/src/flash_map.c b/libs/util/src/flash_map.c
new file mode 100644
index 0000000..28f26c9
--- /dev/null
+++ b/libs/util/src/flash_map.c
@@ -0,0 +1,146 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <hal/hal_flash.h>
+#include <hal/hal_flash_int.h>
+#ifdef NFFS_PRESENT
+#include <nffs/nffs.h>
+#endif
+#include "util/flash_map.h"
+
+static const struct flash_area *flash_map;
+static int flash_map_entries;
+
+void
+flash_area_init(const struct flash_area *map, int map_entries)
+{
+    flash_map = map;
+    flash_map_entries = map_entries;
+    /*
+     * XXX should we validate this against current flashes?
+     */
+}
+
+int
+flash_area_open(int idx, const struct flash_area **fap)
+{
+    if (!flash_map || idx >= flash_map_entries) {
+        return -1;
+    }
+    *fap = &flash_map[idx];
+    return 0;
+}
+
+void
+flash_area_close(const struct flash_area *fa)
+{
+    /* nothing to do for now */
+}
+
+int
+flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret)
+{
+    int i;
+    const struct hal_flash *hf;
+    const struct flash_area *fa;
+    uint32_t start, size;
+
+    if (!flash_map || idx >= flash_map_entries) {
+        return -1;
+    }
+    *cnt = 0;
+    fa = &flash_map[idx];
+
+    hf = bsp_flash_dev(fa->fa_flash_id);
+    for (i = 0; i < hf->hf_sector_cnt; i++) {
+        hf->hf_itf->hff_sector_info(i, &start, &size);
+        if (start >= fa->fa_off && start < fa->fa_off + fa->fa_size) {
+            if (ret) {
+                ret->fa_flash_id = fa->fa_flash_id;
+                ret->fa_off = start;
+                ret->fa_size = size;
+                ret++;
+            }
+            *cnt = *cnt + 1;
+        }
+    }
+    return 0;
+}
+
+#ifdef NFFS_PRESENT
+int
+flash_area_to_nffs_desc(int idx, int *cnt, struct nffs_area_desc *nad)
+{
+    int i;
+    const struct hal_flash *hf;
+    const struct flash_area *fa;
+    uint32_t start, size;
+
+    if (!flash_map || idx >= flash_map_entries) {
+        return -1;
+    }
+    *cnt = 0;
+    fa = &flash_map[idx];
+
+    hf = bsp_flash_dev(fa->fa_flash_id);
+    for (i = 0; i < hf->hf_sector_cnt; i++) {
+        hf->hf_itf->hff_sector_info(i, &start, &size);
+        if (start >= fa->fa_off && start < fa->fa_off + fa->fa_size) {
+            if (nad) {
+                nad->nad_flash_id = fa->fa_flash_id;
+                nad->nad_offset = start;
+                nad->nad_length = size;
+                nad++;
+            }
+            *cnt = *cnt + 1;
+        }
+    }
+    if (nad) {
+        memset(nad, 0, sizeof(*nad));
+    }
+    return 0;
+}
+#endif /* NFFS_PRESENT */
+
+int
+flash_area_read(const struct flash_area *fa, uint32_t off, void *dst,
+  uint32_t len)
+{
+    if (off > fa->fa_size || off + len > fa->fa_size) {
+        return -1;
+    }
+    return hal_flash_read(fa->fa_flash_id, fa->fa_off + off, dst, len);
+}
+
+int
+flash_area_write(const struct flash_area *fa, uint32_t off, void *src,
+  uint32_t len)
+{
+    if (off > fa->fa_size || off + len > fa->fa_size) {
+        return -1;
+    }
+    return hal_flash_write(fa->fa_flash_id, fa->fa_off + off, src, len);
+}
+
+int
+flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
+{
+    if (off > fa->fa_size || off + len > fa->fa_size) {
+        return -1;
+    }
+    return hal_flash_erase(fa->fa_flash_id, fa->fa_off + off, len);
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/src/log.c
----------------------------------------------------------------------
diff --git a/libs/util/src/log.c b/libs/util/src/log.c
new file mode 100644
index 0000000..5d16364
--- /dev/null
+++ b/libs/util/src/log.c
@@ -0,0 +1,274 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 "util/log.h" 
+#include "util/cbmem.h" 
+
+#include <stdio.h>
+
+#ifdef SHELL_PRESENT
+
+#include <shell/shell.h>
+#include <console/console.h> 
+
+struct shell_cmd shell_log_cmd;
+uint8_t shell_registered;
+
+#endif 
+
+static STAILQ_HEAD(, util_log) g_util_log_list = 
+    STAILQ_HEAD_INITIALIZER(g_util_log_list);
+
+
+#ifdef SHELL_PRESENT 
+
+static int 
+shell_log_dump_entry(struct util_log *log, void *arg, void *dptr, uint16_t len) 
+{
+    struct ul_entry_hdr ueh;
+    char data[128];
+    int dlen;
+    int rc;
+
+    rc = util_log_read(log, dptr, &ueh, 0, sizeof(ueh)); 
+    if (rc != sizeof(ueh)) {
+        goto err;
+    }
+
+    dlen = min(len-sizeof(ueh), 128);
+
+    rc = util_log_read(log, dptr, data, sizeof(ueh), dlen);
+    if (rc < 0) {
+        goto err;
+    }
+    data[rc] = 0;
+
+    /* XXX: This is evil.  newlib printf does not like 64-bit 
+     * values, and this causes memory to be overwritten.  Cast to a 
+     * unsigned 32-bit value for now.
+     */
+    console_printf("[%d] %s\n", (uint32_t) ueh.ue_ts, data);
+
+    return (0);
+err:
+    return (rc);
+}
+
+static int 
+shell_log_dump_all(int argc, char **argv)
+{
+    struct util_log *log;
+    int rc;
+
+    STAILQ_FOREACH(log, &g_util_log_list, ul_next) {
+        rc = util_log_walk(log, shell_log_dump_entry, NULL);
+        if (rc != 0) {
+            goto err;
+        }
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+#endif 
+
+static int 
+ulh_cbmem_append(struct util_log *log, void *buf, int len) 
+{
+    struct cbmem *cbmem;
+    int rc;
+
+    cbmem = (struct cbmem *) log->ul_ulh->ulh_arg;
+
+    rc = cbmem_append(cbmem, buf, len);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+static int 
+ulh_cbmem_read(struct util_log *log, void *dptr, void *buf, uint16_t offset, 
+        uint16_t len) 
+{
+    struct cbmem *cbmem;
+    struct cbmem_entry_hdr *hdr;
+    int rc;
+
+    cbmem = (struct cbmem *) log->ul_ulh->ulh_arg;
+    hdr = (struct cbmem_entry_hdr *) dptr;
+
+    rc = cbmem_read(cbmem, hdr, buf, offset, len);
+
+    return (rc);
+}
+
+static int 
+ulh_cbmem_walk(struct util_log *log, util_log_walk_func_t walk_func, void *arg)
+{
+    struct cbmem *cbmem;
+    struct cbmem_entry_hdr *hdr;
+    struct cbmem_iter iter;
+    int rc;
+
+    cbmem = (struct cbmem *) log->ul_ulh->ulh_arg;
+
+    rc = cbmem_lock_acquire(cbmem);
+    if (rc != 0) {
+        goto err;
+    }
+    
+    cbmem_iter_start(cbmem, &iter);
+    while (1) {
+        hdr = cbmem_iter_next(cbmem, &iter);
+        if (!hdr) {
+            break;
+        }
+
+        rc = walk_func(log, arg, (void *) hdr, hdr->ceh_len);
+        if (rc == 1) {
+            break;
+        }
+    }
+
+    rc = cbmem_lock_release(cbmem);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+static int 
+ulh_cbmem_flush(struct util_log *log)
+{
+    struct cbmem *cbmem;
+    int rc;
+
+    cbmem = (struct cbmem *) log->ul_ulh->ulh_arg;
+    
+    rc = cbmem_flush(cbmem);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+int 
+util_log_cbmem_handler_init(struct ul_handler *handler, struct cbmem *cbmem)
+{
+    handler->ulh_read = ulh_cbmem_read;
+    handler->ulh_append = ulh_cbmem_append;
+    handler->ulh_walk = ulh_cbmem_walk;
+    handler->ulh_flush = ulh_cbmem_flush;
+    handler->ulh_arg = (void *) cbmem;
+
+    return (0);
+}
+
+int 
+util_log_register(char *name, struct util_log *log, struct ul_handler *ulh)
+{
+#ifdef SHELL_PRESENT 
+    if (!shell_registered) {
+        /* register the shell */
+        
+        shell_registered = 1;
+        shell_cmd_register(&shell_log_cmd, "log", shell_log_dump_all);
+    }
+#endif
+
+    log->ul_name = name;
+    log->ul_ulh = ulh;
+
+    STAILQ_INSERT_TAIL(&g_util_log_list, log, ul_next);
+
+    return (0);
+}
+
+int
+util_log_append(struct util_log *log, uint8_t *data, uint16_t len)
+{
+    struct ul_entry_hdr *ue;
+    int rc;
+
+    ue = (struct ul_entry_hdr *) data;
+    ue->ue_ts = (int64_t) os_time_get();
+
+    rc = log->ul_ulh->ulh_append(log, data, len + sizeof(*ue));
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+int 
+util_log_walk(struct util_log *log, util_log_walk_func_t walk_func, void *arg)
+{
+    int rc;
+
+    rc = log->ul_ulh->ulh_walk(log, walk_func, arg);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+int 
+util_log_read(struct util_log *log, void *dptr, void *buf, uint16_t off, 
+        uint16_t len)
+{
+    int rc;
+
+    rc = log->ul_ulh->ulh_read(log, dptr, buf, off, len);
+
+    return (rc);
+}
+
+int 
+util_log_flush(struct util_log *log)
+{
+    int rc;
+
+    rc = log->ul_ulh->ulh_flush(log);
+    if (rc != 0) {
+        goto err;
+    } 
+
+    return (0);
+err:
+    return (rc);
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/src/stats.c
----------------------------------------------------------------------
diff --git a/libs/util/src/stats.c b/libs/util/src/stats.c
new file mode 100644
index 0000000..0d2eb36
--- /dev/null
+++ b/libs/util/src/stats.c
@@ -0,0 +1,218 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 "util/stats.h" 
+
+#ifdef SHELL_PRESENT
+#include "shell/shell.h"
+#include "console/console.h"
+#endif
+
+#include <stdio.h>
+
+STATS_SECT_START(stats)
+    STATS_SECT_ENTRY(num_registered)
+STATS_SECT_END(stats)
+
+STATS_NAME_START(stats)
+    STATS_NAME(stats, num_registered)
+STATS_NAME_END(stats)
+
+STAILQ_HEAD(, stats_hdr) g_stats_registry = 
+    STAILQ_HEAD_INITIALIZER(g_stats_registry);
+
+#ifdef SHELL_PRESENT
+uint8_t stats_shell_registered;
+struct shell_cmd shell_stats_cmd;
+#endif
+
+#ifdef SHELL_PRESENT 
+
+static void 
+shell_stats_display_entry(struct stats_hdr *hdr, uint8_t *ptr)
+{
+    char *name;
+    char buf[12];
+    int ent_n;
+    int len;
+#ifdef STATS_NAME_ENABLE
+    int i;
+#endif
+
+    name = NULL;
+
+#ifdef STATS_NAME_ENABLE
+    for (i = 0; i < hdr->s_map_cnt; i++) {
+        if (hdr->s_map[i].snm_off == ptr) {
+            name = hdr->s_map[i].snm_name;
+            break;
+        }
+    }
+#endif 
+
+    if (name == NULL) {
+        ent_n = (ptr - ((uint8_t *) hdr + sizeof(*hdr))) / hdr->s_size;
+
+        len = snprintf(buf, sizeof(buf), "s%d", ent_n);
+        buf[len] = 0;
+        name = buf;
+    }
+
+    switch (hdr->s_size) {
+        case sizeof(uint16_t):
+            console_printf("%s: %u\n", name, *(uint16_t *) ptr);
+            break;
+        case sizeof(uint32_t):
+            console_printf("%s: %u\n", name, *(uint32_t *) ptr);
+            break;
+        case sizeof(uint64_t):
+            console_printf("%s: %llu\n", name, *(uint64_t *) ptr);
+            break;
+        default:
+            console_printf("Unknown stat size for %s %u\n", name, 
+                    hdr->s_size);
+            break;
+    }
+}
+
+static int 
+shell_stats_display(int argc, char **argv)
+{
+    struct stats_hdr *hdr;
+    char *name;
+    uint8_t *cur;
+    uint8_t *end;
+
+    name = argv[1];
+    if (name == NULL || !strcmp(name, "")) {
+        console_printf("Must specify a statistic name to dump, "
+                "possible names are:\n");
+        STAILQ_FOREACH(hdr, &g_stats_registry, s_next) {
+            console_printf("\t%s\n", hdr->s_name);
+        }
+        goto done;
+    }
+
+
+    hdr = stats_find(name);
+    if (!hdr) {
+        console_printf("Could not find statistic %s\n", name);
+        goto done;
+    }
+
+    cur = (uint8_t *) hdr + sizeof(*hdr);
+    end = (uint8_t *) hdr + sizeof(*hdr) + (hdr->s_size * hdr->s_cnt);
+    while (cur < end) {
+        shell_stats_display_entry(hdr, (uint8_t *) cur);
+        cur += hdr->s_size;
+    }
+
+done:
+    return (0);
+}
+
+#endif
+
+int 
+stats_module_init(void)
+{
+    int rc;
+#ifdef SHELL_PRESENT
+    if (!stats_shell_registered) {
+        stats_shell_registered = 1;
+        shell_cmd_register(&shell_stats_cmd, "stat", shell_stats_display);
+    }
+#endif
+
+    rc = stats_init(STATS_HDR(stats), STATS_SIZE_INIT_PARMS(stats, STATS_SIZE_32), 
+            STATS_NAME_INIT_PARMS(stats));
+    if (rc != 0) {
+        goto err;
+    }
+    
+    rc = stats_register("stat", STATS_HDR(stats));
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+
+int
+stats_init(struct stats_hdr *shdr, uint8_t size, uint8_t cnt, 
+        struct stats_name_map *map, uint8_t map_cnt)
+{
+    memset((uint8_t *) shdr, 0, sizeof(*shdr) + (size * cnt));
+
+    shdr->s_size = size;
+    shdr->s_cnt = cnt;
+#ifdef STATS_NAME_ENABLE
+    shdr->s_map = map;
+    shdr->s_map_cnt = map_cnt;
+#endif
+
+    return (0);
+}
+
+int
+stats_register(char *name, struct stats_hdr *shdr)
+{
+    struct stats_hdr *cur;
+    int rc;
+
+    /* Don't allow duplicate entries, return an error if this stat 
+     * is already registered.
+     */
+    STAILQ_FOREACH(cur, &g_stats_registry, s_next) {
+        if (!strcmp(cur->s_name, name)) {
+            rc = -1;
+            goto err;
+        }
+    }
+
+    shdr->s_name = name;
+
+    STAILQ_INSERT_TAIL(&g_stats_registry, shdr, s_next);
+
+    STATS_INC(stats, num_registered);
+
+    return (0);
+err:
+    return (rc);
+}
+
+struct stats_hdr * 
+stats_find(char *name)
+{
+    struct stats_hdr *cur;
+
+    cur = NULL;
+    STAILQ_FOREACH(cur, &g_stats_registry, s_next) {
+        if (!strcmp(cur->s_name, name)) {
+            break;
+        }
+    }
+
+    return (cur);
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/src/test/cbmem_test.c
----------------------------------------------------------------------
diff --git a/libs/util/src/test/cbmem_test.c b/libs/util/src/test/cbmem_test.c
new file mode 100644
index 0000000..af4b323
--- /dev/null
+++ b/libs/util/src/test/cbmem_test.c
@@ -0,0 +1,173 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <string.h>
+
+#include "testutil/testutil.h"
+#include "util/cbmem.h" 
+
+#define CBMEM1_BUF_SIZE (64 * 1024)
+
+struct cbmem cbmem1;
+uint8_t cbmem1_buf[CBMEM1_BUF_SIZE];
+uint8_t cbmem1_entry[1024];
+
+/*
+ * Things to test.
+ *
+ * - Wrap of the circular buffer.  
+ * - Reading through all entries.
+ */
+
+static void
+setup_cbmem1(void)
+{
+    int i;
+    int rc;
+
+    rc = cbmem_init(&cbmem1, cbmem1_buf, CBMEM1_BUF_SIZE);
+    TEST_ASSERT_FATAL(rc == 0, "cbmem_init() failed, non-zero RC = %d", rc);
+
+    memset(cbmem1_entry, 0xff, sizeof(cbmem1_entry));
+
+    /* Insert 65 1024 entries, and overflow buffer.  
+     * This should overflow two entries, because the buffer is sized for 64 
+     * entries, and then the headers themselves will eat into one of the entries, 
+     * so there should be a total of 63 entries.
+     * Ensure no data corruption.
+     */
+    for (i = 0; i < 65; i++) {
+        cbmem1_entry[0] = i;
+        rc = cbmem_append(&cbmem1, cbmem1_entry, sizeof(cbmem1_entry));
+        TEST_ASSERT_FATAL(rc == 0, "Could not append entry %d, rc = %d", i, rc);
+    }
+}
+
+static int 
+cbmem_test_case_1_walk(struct cbmem *cbmem, struct cbmem_entry_hdr *hdr, 
+        void *arg)
+{
+    uint8_t expected;
+    uint8_t actual;
+    int rc;
+
+    expected = *(uint8_t *) arg;
+
+    rc = cbmem_read(cbmem, hdr, &actual, 0, sizeof(actual));
+    TEST_ASSERT_FATAL(rc == 1, "Couldn't read 1 byte from cbmem");
+    TEST_ASSERT_FATAL(actual == expected, 
+            "Actual doesn't equal expected (%d = %d)", actual, expected);
+
+    *(uint8_t *) arg = ++expected;
+
+    return (0);
+}
+
+TEST_CASE(cbmem_test_case_1) 
+{
+    int i;
+    int rc;
+
+    /* i starts at 2, for the 2 overwritten entries. */
+    i = 2;
+    rc = cbmem_walk(&cbmem1, cbmem_test_case_1_walk, &i);
+    TEST_ASSERT_FATAL(rc == 0, "Could not walk cbmem tree!  rc = %d", rc);
+    TEST_ASSERT_FATAL(i == 65, 
+            "Did not go through every element of walk, %d processed", i - 2);
+
+}
+
+TEST_CASE(cbmem_test_case_2)
+{
+    struct cbmem_entry_hdr *hdr;
+    struct cbmem_iter iter;
+    uint8_t i;
+    uint8_t val;
+    int rc;
+
+    i = 2;
+    cbmem_iter_start(&cbmem1, &iter);
+    while (1) {
+        hdr = cbmem_iter_next(&cbmem1, &iter);
+        if (hdr == NULL) {
+            break;
+        }
+
+        rc = cbmem_read(&cbmem1, hdr, &val, 0, sizeof(val));
+        TEST_ASSERT_FATAL(rc == 1, "Couldn't read 1 byte from cbmem");
+        TEST_ASSERT_FATAL(val == i, "Entry index does not match %d vs %d", 
+                val, i);
+
+        i++;
+    }
+
+    /* i starts at 2, for the 2 overwritten entries */
+    TEST_ASSERT_FATAL(i == 65, 
+            "Did not iterate through all 63 elements of CBMEM1, processed %d", 
+            i - 2);
+}
+
+TEST_CASE(cbmem_test_case_3)
+{
+    struct cbmem_entry_hdr *hdr;
+    struct cbmem_iter iter;
+    uint16_t off;
+    uint16_t len;
+    uint8_t buf[128];
+    int i;
+    int rc;
+
+    i = 0;
+    cbmem_iter_start(&cbmem1, &iter);
+    while (1) {
+        hdr = cbmem_iter_next(&cbmem1, &iter);
+        if (hdr == NULL) {
+            break;
+        }
+        
+        /* first ensure we can read the entire entry */
+        off = 0;
+        len = 0;
+        while (1) {
+            rc = cbmem_read(&cbmem1, hdr, buf, off, sizeof(buf));
+            TEST_ASSERT_FATAL(rc >= 0,
+                    "Error reading from buffer rc=%d, off=%d,len=%d", rc, off, 
+                    sizeof(buf));
+            if (rc == 0) {
+                break;
+            }
+            off += rc;
+            len += rc;
+        }
+        TEST_ASSERT_FATAL(len == 1024, 
+                "Couldn't read full entry, expected %d got %d", 1024, len);
+        i++;
+
+        /* go apesh*t, and read data out of bounds, see what we get. */
+        rc = cbmem_read(&cbmem1, hdr, buf, 2048, sizeof(buf));
+        TEST_ASSERT_FATAL(rc < 0, 
+                "Reading invalid should return error, instead %d returned.",
+                rc);
+    }
+}
+
+TEST_SUITE(cbmem_test_suite)
+{
+    setup_cbmem1();
+    cbmem_test_case_1();
+    cbmem_test_case_2();
+    cbmem_test_case_3();
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/src/test/flash_map_test.c
----------------------------------------------------------------------
diff --git a/libs/util/src/test/flash_map_test.c b/libs/util/src/test/flash_map_test.c
new file mode 100644
index 0000000..005139c
--- /dev/null
+++ b/libs/util/src/test/flash_map_test.c
@@ -0,0 +1,151 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <string.h>
+
+#include "os/os.h"
+#include "testutil/testutil.h"
+#include "util/flash_map.h"
+
+#include "hal/hal_flash.h"
+#include "hal/hal_flash_int.h"
+
+/*
+ * Test flash_area_to_sectors()
+ */
+TEST_CASE(flash_map_test_case_1)
+{
+    const struct flash_area *fa;
+    int areas_checked = 0;
+    int i, j, rc;
+    const struct hal_flash *hf;
+    struct flash_area my_secs[32];
+    int my_sec_cnt;
+    uint32_t end;
+
+    os_init();
+
+    for (i = 0; i < 8; i++) {
+        rc = flash_area_open(i, &fa);
+        if (rc) {
+            continue;
+        }
+
+        hf = bsp_flash_dev(fa->fa_flash_id);
+        TEST_ASSERT_FATAL(hf != NULL, "bsp_flash_dev");
+
+        rc = flash_area_to_sectors(i, &my_sec_cnt, my_secs);
+        TEST_ASSERT_FATAL(rc == 0, "flash_area_to_sectors failed");
+
+        end = fa->fa_off;
+        for (j = 0; j < my_sec_cnt; j++) {
+            TEST_ASSERT_FATAL(end == my_secs[j].fa_off, "Non contiguous area");
+            TEST_ASSERT_FATAL(my_secs[j].fa_flash_id == fa->fa_flash_id,
+              "Sectors not in same flash?");
+            end = my_secs[j].fa_off + my_secs[j].fa_size;
+        }
+        if (my_sec_cnt) {
+            areas_checked++;
+            TEST_ASSERT_FATAL(my_secs[my_sec_cnt - 1].fa_off +
+              my_secs[my_sec_cnt - 1].fa_size == fa->fa_off + fa->fa_size,
+              "Last sector not in the end");
+        }
+    }
+    TEST_ASSERT_FATAL(areas_checked != 0, "No flash map areas to check!");
+}
+
+/*
+ * Test flash_erase
+ */
+TEST_CASE(flash_map_test_case_2)
+{
+    const struct flash_area *fa;
+    struct flash_area secs[32];
+    int sec_cnt;
+    int i;
+    int rc;
+    uint32_t off;
+    uint8_t wd[256];
+    uint8_t rd[256];
+
+    os_init();
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_0, &fa);
+    TEST_ASSERT_FATAL(rc == 0, "flash_area_open() fail");
+
+    rc = flash_area_to_sectors(FLASH_AREA_IMAGE_0, &sec_cnt, secs);
+    TEST_ASSERT_FATAL(rc == 0, "flash_area_to_sectors failed");
+
+    /*
+     * First erase the area so it's ready for use.
+     */
+    for (i = 0; i < sec_cnt; i++) {
+        rc = hal_flash_erase_sector(secs[i].fa_flash_id, secs[i].fa_off);
+        TEST_ASSERT_FATAL(rc == 0, "hal_flash_erase_sector() failed");
+    }
+    TEST_ASSERT_FATAL(rc == 0, "read data != write data");
+
+    memset(wd, 0xa5, sizeof(wd));
+
+    /* write stuff to beginning of every sector */
+    off = 0;
+    for (i = 0; i < sec_cnt; i++) {
+        rc = flash_area_write(fa, off, wd, sizeof(wd));
+        TEST_ASSERT_FATAL(rc == 0, "flash_area_write() fail");
+
+        /* read it back via hal_flash_Read() */
+        rc = hal_flash_read(fa->fa_flash_id, fa->fa_off + off, rd, sizeof(rd));
+        TEST_ASSERT_FATAL(rc == 0, "hal_flash_read() fail");
+
+        rc = memcmp(wd, rd, sizeof(wd));
+        TEST_ASSERT_FATAL(rc == 0, "read data != write data");
+
+        /* write stuff to end of area */
+        rc = hal_flash_write(fa->fa_flash_id,
+          fa->fa_off + off + secs[i].fa_size - sizeof(wd), wd, sizeof(wd));
+        TEST_ASSERT_FATAL(rc == 0, "hal_flash_write() fail");
+
+        /* and read it back */
+        memset(rd, 0, sizeof(rd));
+        rc = flash_area_read(fa, off + secs[i].fa_size - sizeof(rd),
+          rd, sizeof(rd));
+        TEST_ASSERT_FATAL(rc == 0, "hal_flash_read() fail");
+
+        rc = memcmp(wd, rd, sizeof(rd));
+        TEST_ASSERT_FATAL(rc == 0, "read data != write data");
+
+        off += secs[i].fa_size;
+    }
+    /* erase it */
+    rc = flash_area_erase(fa, 0, fa->fa_size);
+    TEST_ASSERT_FATAL(rc == 0, "read data != write data");
+
+    /* should read back ff all throughout*/
+    memset(wd, 0xff, sizeof(wd));
+    for (off = 0; off < fa->fa_size; off += sizeof(rd)) {
+         rc = flash_area_read(fa, off, rd, sizeof(rd));
+         TEST_ASSERT_FATAL(rc == 0, "hal_flash_read() fail");
+
+         rc = memcmp(wd, rd, sizeof(rd));
+         TEST_ASSERT_FATAL(rc == 0, "area not erased");
+    }
+}
+
+TEST_SUITE(flash_map_test_suite)
+{
+    flash_map_test_case_1();
+    flash_map_test_case_2();
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/src/test/util_test.c
----------------------------------------------------------------------
diff --git a/libs/util/src/test/util_test.c b/libs/util/src/test/util_test.c
new file mode 100644
index 0000000..9998fa7
--- /dev/null
+++ b/libs/util/src/test/util_test.c
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <stddef.h>
+#include "testutil/testutil.h"
+#include "util_test_priv.h"
+
+int
+util_test_all(void)
+{
+    cbmem_test_suite();
+    flash_map_test_suite();
+    return tu_case_failed;
+}
+
+#ifdef PKG_TEST
+
+int
+main(int argc, char **argv)
+{
+    tu_config.tc_print_results = 1;
+    tu_init();
+
+    util_test_all();
+
+    return tu_any_failed;
+}
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/src/test/util_test_priv.h
----------------------------------------------------------------------
diff --git a/libs/util/src/test/util_test_priv.h b/libs/util/src/test/util_test_priv.h
new file mode 100644
index 0000000..d6f8da4
--- /dev/null
+++ b/libs/util/src/test/util_test_priv.h
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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_TEST_PRIV_
+#define __UTIL_TEST_PRIV_
+
+int cbmem_test_suite(void);
+int flash_map_test_suite(void);
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/util/src/tpq.c
----------------------------------------------------------------------
diff --git a/libs/util/src/tpq.c b/libs/util/src/tpq.c
new file mode 100644
index 0000000..72133c0
--- /dev/null
+++ b/libs/util/src/tpq.c
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 "util/tpq.h"
+
+/**
+ * Put an element on a task packet queue and post an event to an event queue. 
+ * 
+ * @param evq   Pointer to event queue
+ * @param tpq   Pointer to task packet queue
+ * @param elem  Pointer to element to enqueue
+ */
+void
+tpq_put(struct os_eventq *evq, struct tpq *tpq, struct tpq_elem *elem)
+{
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    STAILQ_INSERT_TAIL(&tpq->tpq_head, elem, tpq_next);
+    OS_EXIT_CRITICAL(sr);
+    os_eventq_put(evq, &tpq->tpq_ev);
+}
+
+/**
+ * Retrieve an element from a task packet queue. This removes the element at 
+ * the head of the queue. 
+ * 
+ * @param head 
+ * 
+ * @return struct tpq_elem* 
+ */
+struct tpq_elem *
+tpq_get(struct tpq *tpq)
+{
+    os_sr_t sr;
+    struct tpq_elem *elem;
+
+    OS_ENTER_CRITICAL(sr);
+    elem = STAILQ_FIRST(&tpq->tpq_head);
+    if (elem) {
+        STAILQ_REMOVE_HEAD(&tpq->tpq_head, tpq_next);
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    return elem;
+}
+
+/**
+ * Initialize a task packet queue 
+ * 
+ * @param tpq Pointer to task packet queue
+ * @param ev_type Type of event.
+ * @param ev_arg Argument of event
+ * 
+ * @return int 
+ */
+void
+tpq_init(struct tpq *tpq, uint8_t ev_type, void *ev_arg)
+{
+    struct os_event *ev;
+
+    /* Initialize the task packet queue */
+    STAILQ_INIT(&tpq->tpq_head);
+
+    /* Initial task packet queue event */
+    ev = &tpq->tpq_ev;
+    ev->ev_arg = ev_arg;
+    ev->ev_type = ev_type;
+    ev->ev_queued = 0;
+    STAILQ_NEXT(ev, ev_next) = NULL;
+}
+


[2/2] incubator-mynewt-tadpole git commit: Merge larva changes to tadpole.

Posted by ma...@apache.org.
Merge larva changes to tadpole.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/commit/29ce5cdc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/tree/29ce5cdc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/diff/29ce5cdc

Branch: refs/heads/master
Commit: 29ce5cdc6409e210c12fb2eef8d222dd21efac12
Parents: ad160f5
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Mon Nov 30 12:55:58 2015 -0800
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Mon Nov 30 12:55:58 2015 -0800

----------------------------------------------------------------------
 compiler/sim/compiler.yml                      |   2 +-
 compiler/sim/linux-compiler.yml                |   7 +-
 compiler/sim/osx-compiler.yml                  |   2 +-
 hw/bsp/native/egg.yml                          |   3 +
 hw/bsp/native/src/hal_bsp.c                    |  34 ++
 hw/bsp/native/src/os_bsp.c                     |  53 ++
 hw/bsp/native/src/sbrk.c                       |  56 ++
 hw/hal/include/hal/hal_cputime.h               |   2 +-
 hw/hal/include/hal/hal_flash.h                 |  14 +-
 hw/hal/include/hal/hal_flash_int.h             |  47 ++
 hw/hal/include/hal/hal_spim.h                  |  44 ++
 hw/hal/include/hal/hal_system.h                |   2 +-
 hw/hal/include/hal/hal_uart.h                  |  11 +-
 hw/hal/src/hal_flash.c                         | 153 ++++++
 hw/mcu/native/include/mcu/mcu_sim.h            |  23 +
 hw/mcu/native/include/mcu/native_bsp.h         |  21 +
 hw/mcu/native/src/hal_cputime.c                | 490 +++++++++++++++++
 hw/mcu/native/src/hal_flash.c                  | 257 ++++-----
 hw/mcu/native/src/hal_gpio.c                   |   1 -
 hw/mcu/native/src/hal_system.c                 |  49 +-
 hw/mcu/native/src/hal_uart.c                   |  90 +++-
 libs/os/egg.yml                                |  10 +
 libs/os/include/os/arch/cortex_m4/os/os_arch.h |   4 +-
 libs/os/include/os/arch/sim/os/os_arch.h       |   2 +
 libs/os/include/os/os.h                        |   3 +
 libs/os/include/os/os_eventq.h                 |   3 +
 libs/os/include/os/os_mbuf.h                   | 115 ++--
 libs/os/include/os/os_sched.h                  |   4 +
 libs/os/include/os/os_task.h                   |   7 +-
 libs/os/include/os/os_time.h                   |   7 +-
 libs/os/src/arch/cortex_m4/m4/HAL_CM4.s        |  30 ++
 libs/os/src/arch/cortex_m4/os_arch_arm.c       |  41 +-
 libs/os/src/arch/cortex_m4/os_fault.c          |  85 +++
 libs/os/src/arch/sim/os_arch_sim.c             |  15 +-
 libs/os/src/arch/sim/os_fault.c                |  30 ++
 libs/os/src/os.c                               |   3 +
 libs/os/src/os_info.c                          | 169 ++++++
 libs/os/src/os_mbuf.c                          | 568 +++++++++++++++++++-
 libs/os/src/os_sched.c                         |  56 +-
 libs/os/src/os_task.c                          |   6 +
 libs/os/src/os_time.c                          |   2 +-
 libs/os/src/test/mbuf_test.c                   |  18 +-
 libs/testutil/src/suite.c                      |   4 +-
 libs/util/egg.yml                              |  13 +
 libs/util/include/util/cbmem.h                 |  63 +++
 libs/util/include/util/flash_map.h             |  88 +++
 libs/util/include/util/log.h                   |  61 +++
 libs/util/include/util/stats.h                 | 108 ++++
 libs/util/include/util/tpq.h                   |  64 +++
 libs/util/include/util/util.h                  |  19 +
 libs/util/src/cbmem.c                          | 269 +++++++++
 libs/util/src/flash_map.c                      | 146 +++++
 libs/util/src/log.c                            | 274 ++++++++++
 libs/util/src/stats.c                          | 218 ++++++++
 libs/util/src/test/cbmem_test.c                | 173 ++++++
 libs/util/src/test/flash_map_test.c            | 151 ++++++
 libs/util/src/test/util_test.c                 |  43 ++
 libs/util/src/test/util_test_priv.h            |  23 +
 libs/util/src/tpq.c                            |  85 +++
 59 files changed, 4042 insertions(+), 299 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/compiler/sim/compiler.yml
----------------------------------------------------------------------
diff --git a/compiler/sim/compiler.yml b/compiler/sim/compiler.yml
index 6803c63..fd61dc9 100644
--- a/compiler/sim/compiler.yml
+++ b/compiler/sim/compiler.yml
@@ -23,7 +23,7 @@ compiler.path.objsize: "objsize"
 compiler.path.objcopy: "gobjcopy"
 
 compiler.flags.base: >
-    -m32 -Wall -Werror -ggdb -O0
+    -m32 -Wall -Werror -ggdb -O0 -DMN_OSX
 
 compiler.flags.default: [compiler.flags.base]
 compiler.flags.debug: [compiler.flags.base, -ggdb -O0]

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/compiler/sim/linux-compiler.yml
----------------------------------------------------------------------
diff --git a/compiler/sim/linux-compiler.yml b/compiler/sim/linux-compiler.yml
index 3dac5f2..d9603ec 100644
--- a/compiler/sim/linux-compiler.yml
+++ b/compiler/sim/linux-compiler.yml
@@ -16,17 +16,18 @@
 
 ############################# Compiler Variables #############################
 
-compiler.path.cc: "gcc" 
+compiler.path.cc: "gcc"
 compiler.path.archive: "ar"
 compiler.path.objdump: "objdump"
-compiler.path.objsize: "objsize"
+compiler.path.objsize: "size"
 compiler.path.objcopy: "objcopy"
 
 compiler.flags.base: >
-    -m32 -Wall -Werror -ggdb -O0
+    -m32 -Wall -Werror -ggdb -O0 -DMN_LINUX
 
 compiler.flags.default: [compiler.flags.base]
 compiler.flags.debug: [compiler.flags.base, -ggdb -O0]
 
 compiler.ld.mapfile: false
 compiler.ld.resolve_circular_deps: true
+compiler.ld.flags: -lutil

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/compiler/sim/osx-compiler.yml
----------------------------------------------------------------------
diff --git a/compiler/sim/osx-compiler.yml b/compiler/sim/osx-compiler.yml
index 6803c63..fd61dc9 100644
--- a/compiler/sim/osx-compiler.yml
+++ b/compiler/sim/osx-compiler.yml
@@ -23,7 +23,7 @@ compiler.path.objsize: "objsize"
 compiler.path.objcopy: "gobjcopy"
 
 compiler.flags.base: >
-    -m32 -Wall -Werror -ggdb -O0
+    -m32 -Wall -Werror -ggdb -O0 -DMN_OSX
 
 compiler.flags.default: [compiler.flags.base]
 compiler.flags.debug: [compiler.flags.base, -ggdb -O0]

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/bsp/native/egg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/native/egg.yml b/hw/bsp/native/egg.yml
index 64a7a20..8e0741c 100644
--- a/hw/bsp/native/egg.yml
+++ b/hw/bsp/native/egg.yml
@@ -1,3 +1,6 @@
 egg.name: "hw/bsp/native"
 egg.deps: 
     - hw/mcu/native
+    - libs/util
+egg.deps.BLE_DEVICE:
+    - net/nimble/drivers/native

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/bsp/native/src/hal_bsp.c
----------------------------------------------------------------------
diff --git a/hw/bsp/native/src/hal_bsp.c b/hw/bsp/native/src/hal_bsp.c
new file mode 100644
index 0000000..389c49a
--- /dev/null
+++ b/hw/bsp/native/src/hal_bsp.c
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <assert.h>
+#include <string.h>
+#include <inttypes.h>
+#include "hal/hal_flash_int.h"
+#include "mcu/native_bsp.h"
+
+const struct hal_flash *
+bsp_flash_dev(uint8_t id)
+{
+    /*
+     * Just one to start with
+     */
+    if (id != 0) {
+        return NULL;
+    }
+    return &native_flash_dev;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/bsp/native/src/os_bsp.c
----------------------------------------------------------------------
diff --git a/hw/bsp/native/src/os_bsp.c b/hw/bsp/native/src/os_bsp.c
new file mode 100644
index 0000000..cc414da
--- /dev/null
+++ b/hw/bsp/native/src/os_bsp.c
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <util/flash_map.h>
+
+static struct flash_area bsp_flash_areas[] = {
+    [FLASH_AREA_BOOTLOADER] = {
+        .fa_flash_id = 0,       /* internal flash */
+        .fa_off = 0x00000000,   /* beginning */
+        .fa_size = (32 * 1024)
+    },
+    /* 2 * 16K and 1*64K sectors here */
+    [FLASH_AREA_IMAGE_0] = {
+        .fa_flash_id = 0,
+        .fa_off = 0x00020000,
+        .fa_size = (384 * 1024)
+    },
+    [FLASH_AREA_IMAGE_1] = {
+        .fa_flash_id = 0,
+        .fa_off = 0x00080000,
+        .fa_size = (384 * 1024)
+    },
+    [FLASH_AREA_IMAGE_SCRATCH] = {
+        .fa_flash_id = 0,
+        .fa_off = 0x000e0000,
+        .fa_size = (128 * 1024)
+    },
+    [FLASH_AREA_NFFS] = {
+        .fa_flash_id = 0,
+        .fa_off = 0x00008000,
+        .fa_size = (32 * 1024)
+    }
+
+};
+
+void os_bsp_init(void)
+{
+    flash_area_init(bsp_flash_areas,
+      sizeof(bsp_flash_areas) / sizeof(bsp_flash_areas[0]));
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/bsp/native/src/sbrk.c
----------------------------------------------------------------------
diff --git a/hw/bsp/native/src/sbrk.c b/hw/bsp/native/src/sbrk.c
new file mode 100644
index 0000000..154bd39
--- /dev/null
+++ b/hw/bsp/native/src/sbrk.c
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <sys/mman.h>
+#include <unistd.h>
+#include <errno.h>
+
+extern int getpagesize(void);
+
+static void *cont;
+static int sys_pagesize;
+static int cont_left;
+
+void *
+_sbrk(int incr)
+{
+    void *result;
+
+    if (!sys_pagesize) {
+        sys_pagesize = getpagesize();
+    }
+    if (cont && incr <= cont_left) {
+        result = cont;
+        cont_left -= incr;
+        if (cont_left) {
+            cont = (char *)cont + incr;
+        } else {
+            cont = NULL;
+        }
+        return result;
+    }
+    result = mmap(NULL, incr, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED,
+      -1, 0);
+    if (result) {
+        cont_left = sys_pagesize - (incr % sys_pagesize);
+        if (cont_left) {
+            cont = (char *)result + incr;
+        } else {
+            cont = NULL;
+        }
+    }
+    return result;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/hal/include/hal/hal_cputime.h
----------------------------------------------------------------------
diff --git a/hw/hal/include/hal/hal_cputime.h b/hw/hal/include/hal/hal_cputime.h
index 286736c..97d8709 100644
--- a/hw/hal/include/hal/hal_cputime.h
+++ b/hw/hal/include/hal/hal_cputime.h
@@ -170,7 +170,7 @@ void cputime_timer_relative(struct cpu_timer *timer, uint32_t usecs);
  *  
  * 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 running. 
+ * called even if timer is not running. 
  * 
  * @param timer Pointer to cputimer to stop. Cannot be NULL.
  */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/hal/include/hal/hal_flash.h
----------------------------------------------------------------------
diff --git a/hw/hal/include/hal/hal_flash.h b/hw/hal/include/hal/hal_flash.h
index 98813d1..be3b358 100644
--- a/hw/hal/include/hal/hal_flash.h
+++ b/hw/hal/include/hal/hal_flash.h
@@ -4,7 +4,7 @@
  * Licensed 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
@@ -19,11 +19,13 @@
 
 #include <inttypes.h>
 
-int flash_read(uint32_t address, void *dst, uint32_t num_bytes);
-int flash_write(uint32_t address, const void *src, uint32_t num_bytes);
-int flash_erase_sector(uint32_t sector_address);
-int flash_erase(uint32_t address, uint32_t num_bytes);
-int flash_init(void);
+int hal_flash_read(uint8_t flash_id, uint32_t address, void *dst,
+  uint32_t num_bytes);
+int hal_flash_write(uint8_t flash_id, uint32_t address, const void *src,
+  uint32_t num_bytes);
+int hal_flash_erase_sector(uint8_t flash_id, uint32_t sector_address);
+int hal_flash_erase(uint8_t flash_id, uint32_t address, uint32_t num_bytes);
+int hal_flash_init(void);
 
 #endif
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/hal/include/hal/hal_flash_int.h
----------------------------------------------------------------------
diff --git a/hw/hal/include/hal/hal_flash_int.h b/hw/hal/include/hal/hal_flash_int.h
new file mode 100644
index 0000000..ab7e159
--- /dev/null
+++ b/hw/hal/include/hal/hal_flash_int.h
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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_FLASH_INT
+#define H_HAL_FLASH_INT
+
+#include <inttypes.h>
+/*
+ * API that flash driver has to implement.
+ */
+struct hal_flash_funcs {
+    int (*hff_read)(uint32_t address, void *dst, uint32_t num_bytes);
+    int (*hff_write)(uint32_t address, const void *src, uint32_t num_bytes);
+    int (*hff_erase_sector)(uint32_t sector_address);
+    int (*hff_sector_info)(int idx, uint32_t *address, uint32_t *size);
+    int (*hff_init)(void);
+};
+
+struct hal_flash {
+    const struct hal_flash_funcs *hf_itf;
+    uint32_t hf_base_addr;
+    uint32_t hf_size;
+    int hf_sector_cnt;
+};
+
+/*
+ * Return size of the flash sector. sec_idx is index to hf_sectors array.
+ */
+uint32_t hal_flash_sector_size(const struct hal_flash *hf, int sec_idx);
+
+/* External function prototype supplied by BSP */
+const struct hal_flash *bsp_flash_dev(uint8_t flash_id);
+
+#endif /* H_HAL_FLASH_INT */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/hal/include/hal/hal_spim.h
----------------------------------------------------------------------
diff --git a/hw/hal/include/hal/hal_spim.h b/hw/hal/include/hal/hal_spim.h
new file mode 100644
index 0000000..fa1eeeb
--- /dev/null
+++ b/hw/hal/include/hal/hal_spim.h
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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_SPIM_H_
+#define H_HAL_SPIM_H_
+
+#include <inttypes.h>
+
+/**
+ *
+ * hal_spim_init()
+ *
+ * Sets up a SPI master port ready for data transfer.
+ * Mapping logical port number to pins is dictated by BSP.
+ */
+int hal_spim_init(int port, int mode, int speed);
+
+/*
+ * hal_spim_select()/hal_spim_deselect.
+ * Assert and deassert chip select for the target, respectively.
+ */
+int hal_spim_select(int port);
+int hal_spim_deselect(int port);
+
+/**
+ *
+ * hal_spim_txrx()
+ * Initiate data transfer. Specify TX data or RX data, or both.
+ */
+int hal_spim_txrx(int port, void *tx_buf, int tx_len, void *rx_buf, int rx_len);
+
+#endif /* H_HAL_SPIM_H_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/hal/include/hal/hal_system.h
----------------------------------------------------------------------
diff --git a/hw/hal/include/hal/hal_system.h b/hw/hal/include/hal/hal_system.h
index 3d5569c..19f5ed1 100644
--- a/hw/hal/include/hal/hal_system.h
+++ b/hw/hal/include/hal/hal_system.h
@@ -17,6 +17,6 @@
 #ifndef H_HAL_SYSTEM_
 #define H_HAL_SYSTEM_
 
-void system_reset(void);
+void system_reset(void) __attribute((noreturn));
 
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/hal/include/hal/hal_uart.h
----------------------------------------------------------------------
diff --git a/hw/hal/include/hal/hal_uart.h b/hw/hal/include/hal/hal_uart.h
index 6dc47bd..b308b84 100644
--- a/hw/hal/include/hal/hal_uart.h
+++ b/hw/hal/include/hal/hal_uart.h
@@ -41,7 +41,7 @@ typedef void (*hal_uart_tx_done)(void *arg);
 typedef int (*hal_uart_rx_char)(void *arg, uint8_t byte);
 
 /**
- * hal uart init
+ * hal uart init cbs
  *
  * Initializes given uart. Mapping of logical UART number to physical
  * UART/GPIO pins is in BSP.
@@ -85,4 +85,13 @@ void hal_uart_start_tx(int uart);
  */
 void hal_uart_start_rx(int uart);
 
+/**
+ * hal uart blocking tx
+ *
+ * This is type of write where UART has to block until character has been sent.
+ * Used when printing diag output from system crash.
+ * Must be called with interrupts disabled.
+ */
+void hal_uart_blocking_tx(int uart, uint8_t byte);
+
 #endif /* H_HAL_UART_H_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/hal/src/hal_flash.c
----------------------------------------------------------------------
diff --git a/hw/hal/src/hal_flash.c b/hw/hal/src/hal_flash.c
new file mode 100644
index 0000000..90fd985
--- /dev/null
+++ b/hw/hal/src/hal_flash.c
@@ -0,0 +1,153 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <inttypes.h>
+#include <assert.h>
+#include <bsp/bsp.h>
+
+#include "hal/hal_flash.h"
+#include "hal/hal_flash_int.h"
+
+int
+hal_flash_init(void)
+{
+    const struct hal_flash *hf;
+    uint8_t i;
+    int rc = 0;
+
+    for (i = 0; ; i++) {
+        hf = bsp_flash_dev(i);
+        if (!hf) {
+            break;
+        }
+        if (hf->hf_itf->hff_init()) {
+            rc = -1;
+        }
+    }
+    return rc;
+}
+
+uint32_t
+hal_flash_sector_size(const struct hal_flash *hf, int sec_idx)
+{
+    uint32_t size;
+    uint32_t start;
+
+    if (hf->hf_itf->hff_sector_info(sec_idx, &start, &size)) {
+        return 0;
+    }
+    return size;
+}
+
+static int
+hal_flash_check_addr(const struct hal_flash *hf, uint32_t addr)
+{
+    if (addr < hf->hf_base_addr || addr > hf->hf_base_addr + hf->hf_size) {
+        return -1;
+    }
+    return 0;
+}
+
+int
+hal_flash_read(uint8_t id, uint32_t address, void *dst, uint32_t num_bytes)
+{
+    const struct hal_flash *hf;
+
+    hf = bsp_flash_dev(id);
+    if (!hf) {
+        return -1;
+    }
+    if (hal_flash_check_addr(hf, address) ||
+      hal_flash_check_addr(hf, address + num_bytes)) {
+        return -1;
+    }
+    return hf->hf_itf->hff_read(address, dst, num_bytes);
+}
+
+int
+hal_flash_write(uint8_t id, uint32_t address, const void *src,
+  uint32_t num_bytes)
+{
+    const struct hal_flash *hf;
+
+    hf = bsp_flash_dev(id);
+    if (!hf) {
+        return -1;
+    }
+    if (hal_flash_check_addr(hf, address) ||
+      hal_flash_check_addr(hf, address + num_bytes)) {
+        return -1;
+    }
+    return hf->hf_itf->hff_write(address, src, num_bytes);
+}
+
+int
+hal_flash_erase_sector(uint8_t id, uint32_t sector_address)
+{
+    const struct hal_flash *hf;
+
+    hf = bsp_flash_dev(id);
+    if (!hf) {
+        return -1;
+    }
+    if (hal_flash_check_addr(hf, sector_address)) {
+        return -1;
+    }
+    return hf->hf_itf->hff_erase_sector(sector_address);
+}
+
+int
+hal_flash_erase(uint8_t id, uint32_t address, uint32_t num_bytes)
+{
+    const struct hal_flash *hf;
+    uint32_t start, size;
+    uint32_t end;
+    uint32_t end_area;
+    int i;
+    int rc;
+
+    hf = bsp_flash_dev(id);
+    if (!hf) {
+        return -1;
+    }
+    if (hal_flash_check_addr(hf, address) ||
+      hal_flash_check_addr(hf, address + num_bytes)) {
+        return -1;
+    }
+
+    end = address + num_bytes;
+    if (end <= address) {
+        /*
+         * Check for wrap-around.
+         */
+        return -1;
+    }
+
+    for (i = 0; i < hf->hf_sector_cnt; i++) {
+        rc = hf->hf_itf->hff_sector_info(i, &start, &size);
+        assert(rc == 0);
+        end_area = start + size;
+        if (address < end_area && end > start) {
+            /*
+             * If some region of eraseable area falls inside sector,
+             * erase the sector.
+             */
+            if (hf->hf_itf->hff_erase_sector(start)) {
+                return -1;
+            }
+        }
+    }
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/mcu/native/include/mcu/mcu_sim.h
----------------------------------------------------------------------
diff --git a/hw/mcu/native/include/mcu/mcu_sim.h b/hw/mcu/native/include/mcu/mcu_sim.h
new file mode 100644
index 0000000..7ab0842
--- /dev/null
+++ b/hw/mcu/native/include/mcu/mcu_sim.h
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 __MCU_SIM_H__
+#define __MCU_SIM_H__
+
+extern char *native_flash_file;
+
+void mcu_sim_parse_args(int argc, char **argv);
+
+#endif /* __MCU_SIM_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/mcu/native/include/mcu/native_bsp.h
----------------------------------------------------------------------
diff --git a/hw/mcu/native/include/mcu/native_bsp.h b/hw/mcu/native/include/mcu/native_bsp.h
new file mode 100644
index 0000000..91d41dc
--- /dev/null
+++ b/hw/mcu/native/include/mcu/native_bsp.h
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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_NATIVE_BSP_
+#define H_NATIVE_BSP_
+
+extern const struct hal_flash native_flash_dev;
+
+#endif /* H_NATIVE_BSP_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/mcu/native/src/hal_cputime.c
----------------------------------------------------------------------
diff --git a/hw/mcu/native/src/hal_cputime.c b/hw/mcu/native/src/hal_cputime.c
new file mode 100644
index 0000000..6aef643
--- /dev/null
+++ b/hw/mcu/native/src/hal_cputime.c
@@ -0,0 +1,490 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 "os/os.h"
+#include "hal/hal_cputime.h"
+
+/* CPUTIME data */
+struct cputime_data
+{
+    uint32_t ticks_per_usec;    /* number of ticks per usec */
+    uint32_t timer_isrs;        /* Number of timer interrupts */
+    uint32_t ocmp_ints;         /* Number of ocmp interrupts */
+    uint32_t uif_ints;          /* Number of overflow interrupts */
+    uint32_t last_ostime;
+    uint64_t cputime;           /* 64-bit cputime */
+};
+struct cputime_data g_cputime;
+
+/* Queue for timers */
+TAILQ_HEAD(cputime_qhead, cpu_timer) g_cputimer_q;
+
+/* For native cpu implementation */
+#define NATIVE_CPUTIME_STACK_SIZE   (1024)
+os_stack_t g_native_cputime_stack[NATIVE_CPUTIME_STACK_SIZE];
+struct os_task g_native_cputime_task;
+
+struct os_callout_func g_native_cputimer;
+struct os_eventq g_native_cputime_evq;
+static uint32_t g_native_cputime_cputicks_per_ostick;
+
+
+/**
+ * Convert cpu time ticks to os ticks.
+ * 
+ * 
+ * @param cputicks 
+ * 
+ * @return uint32_t 
+ */
+static uint32_t
+native_cputime_ticks_to_osticks(uint32_t cputicks)
+{
+    uint32_t osticks;
+
+    osticks = cputicks / g_native_cputime_cputicks_per_ostick;
+    return osticks;
+}
+
+/**
+ * cputime set ocmp 
+ *  
+ * Set the OCMP used by the cputime module to the desired cputime. 
+ * 
+ * @param timer Pointer to timer.
+ */
+static void
+cputime_set_ocmp(struct cpu_timer *timer)
+{
+    uint32_t curtime;
+    uint32_t osticks;
+
+    curtime = cputime_get32();
+    if ((int32_t)(timer->cputime - curtime) < 0) {
+        osticks = 0;
+    } else {
+        osticks = native_cputime_ticks_to_osticks(timer->cputime - curtime);
+    }
+
+    /* Re-start the timer */
+    os_callout_reset(&g_native_cputimer.cf_c, osticks);
+}
+
+/**
+ * cputime chk expiration 
+ *  
+ * Iterates through the cputimer queue to determine if any timers have expired. 
+ * If the timer has expired the timer is removed from the queue and the timer 
+ * callback function is executed. 
+ * 
+ */
+static void
+cputime_chk_expiration(void)
+{
+    os_sr_t sr;
+    struct cpu_timer *timer;
+
+    OS_ENTER_CRITICAL(sr);
+    while ((timer = TAILQ_FIRST(&g_cputimer_q)) != NULL) {
+        if ((int32_t)(cputime_get32() - timer->cputime) >= 0) {
+            TAILQ_REMOVE(&g_cputimer_q, timer, link);
+            timer->cb(timer->arg);
+        } else {
+            break;
+        }
+    }
+
+    /* Any timers left on queue? If so, we need to set OCMP */
+    timer = TAILQ_FIRST(&g_cputimer_q);
+    if (timer) {
+        cputime_set_ocmp(timer);
+    } else {
+        os_callout_stop(&g_native_cputimer.cf_c);
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+
+/**
+ * This is the function called when the cputimer fires off. 
+ * 
+ * @param arg 
+ */
+void
+native_cputimer_cb(void *arg)
+{
+    /* Count # of interrupts */
+    ++g_cputime.ocmp_ints;
+
+    /* Execute the timer */
+    cputime_chk_expiration();
+}
+
+void
+native_cputime_task_handler(void *arg)
+{
+    struct os_event *ev;
+    struct os_callout_func *cf;
+
+    while (1) {
+        ev = os_eventq_get(&g_native_cputime_evq);
+        switch (ev->ev_type) {
+        case OS_EVENT_T_TIMER:
+            cf = (struct os_callout_func *)ev;
+            assert(cf->cf_func);
+            cf->cf_func(cf->cf_arg);
+            break;
+        default:
+            assert(0);
+            break;
+        }
+    }
+}
+
+/**
+ * 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
+cputime_init(uint32_t clock_freq)
+{
+    /* Clock frequency must be at least 1 MHz */
+    if (clock_freq < 1000000U) {
+        return -1;
+    }
+
+    /* Initialize the timer queue */
+    TAILQ_INIT(&g_cputimer_q);
+
+    /* Set the clock frequency */
+    g_cputime.ticks_per_usec = clock_freq / 1000000U;
+    g_native_cputime_cputicks_per_ostick = clock_freq / OS_TICKS_PER_SEC;
+
+    os_task_init(&g_native_cputime_task, 
+                 "native_cputimer", 
+                 native_cputime_task_handler, 
+                 NULL, 
+                 OS_TASK_PRI_HIGHEST, 
+                 OS_WAIT_FOREVER, 
+                 g_native_cputime_stack, 
+                 NATIVE_CPUTIME_STACK_SIZE);
+
+    /* Initialize the eventq and task */
+    os_eventq_init(&g_native_cputime_evq);
+
+    /* Initialize the callout function */
+    os_callout_func_init(&g_native_cputimer,
+                         &g_native_cputime_evq,
+                         native_cputimer_cb,
+                         NULL);
+
+    return 0;
+}
+
+/**
+ * cputime get64
+ *  
+ * Returns cputime as a 64-bit number. 
+ * 
+ * @return uint64_t The 64-bit representation of cputime.
+ */
+uint64_t 
+cputime_get64(void)
+{
+    cputime_get32();
+    return g_cputime.cputime;
+}
+
+/**
+ * cputime get32 
+ *  
+ * Returns the low 32 bits of cputime. 
+ * 
+ * @return uint32_t The lower 32 bits of cputime
+ */
+uint32_t
+cputime_get32(void)
+{
+    os_sr_t sr;
+    uint32_t ostime;
+    uint32_t delta_osticks;
+
+    OS_ENTER_CRITICAL(sr);
+    ostime = os_time_get();
+    delta_osticks = (uint32_t)(ostime - g_cputime.last_ostime);
+    if (delta_osticks) {
+        g_cputime.last_ostime = ostime;
+        g_cputime.cputime +=
+            (uint64_t)g_native_cputime_cputicks_per_ostick * delta_osticks;
+
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    return (uint32_t)g_cputime.cputime;
+}
+
+/**
+ * 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 
+cputime_nsecs_to_ticks(uint32_t nsecs)
+{
+    uint32_t ticks;
+
+    ticks = ((nsecs * g_cputime.ticks_per_usec) + 999) / 1000;
+    return ticks;
+}
+
+/**
+ * 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 
+cputime_ticks_to_nsecs(uint32_t ticks)
+{
+    uint32_t nsecs;
+
+    nsecs = ((ticks * 1000) + (g_cputime.ticks_per_usec - 1)) / 
+            g_cputime.ticks_per_usec;
+
+    return nsecs;
+}
+
+/**
+ * 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 
+cputime_usecs_to_ticks(uint32_t usecs)
+{
+    uint32_t ticks;
+
+    ticks = (usecs * g_cputime.ticks_per_usec);
+    return ticks;
+}
+
+/**
+ * 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 
+cputime_ticks_to_usecs(uint32_t ticks)
+{
+    uint32_t us;
+
+    us =  (ticks + (g_cputime.ticks_per_usec - 1)) / g_cputime.ticks_per_usec;
+    return us;
+}
+
+/**
+ * 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 
+cputime_delay_ticks(uint32_t ticks)
+{
+    uint32_t until;
+
+    until = cputime_get32() + ticks;
+    while ((int32_t)(cputime_get32() - until) < 0) {
+        /* Loop here till finished */
+    }
+}
+
+/**
+ * cputime delay nsecs 
+ *  
+ * Wait until 'nsecs' nanoseconds has elapsed. This is a blocking delay. 
+ *  
+ * @param nsecs The number of nanoseconds to wait.
+ */
+void 
+cputime_delay_nsecs(uint32_t nsecs)
+{
+    uint32_t ticks;
+
+    ticks = cputime_nsecs_to_ticks(nsecs);
+    cputime_delay_ticks(ticks);
+}
+
+/**
+ * cputime delay usecs 
+ *  
+ * Wait until 'usecs' microseconds has elapsed. This is a blocking delay. 
+ *  
+ * @param usecs The number of usecs to wait.
+ */
+void 
+cputime_delay_usecs(uint32_t usecs)
+{
+    uint32_t ticks;
+
+    ticks = cputime_usecs_to_ticks(usecs);
+    cputime_delay_ticks(ticks);
+}
+
+/**
+ * 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 
+cputime_timer_init(struct cpu_timer *timer, cputimer_func fp, void *arg)
+{
+    assert(timer != NULL);
+    assert(fp != NULL);
+
+    timer->cb = fp;
+    timer->arg = arg;
+    timer->link.tqe_prev = (void *) NULL;
+}
+
+/**
+ * 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). 
+ * 
+ * @param timer     Pointer to timer to start. Cannot be NULL.
+ * @param cputime   The cputime at which the timer should expire.
+ */
+void 
+cputime_timer_start(struct cpu_timer *timer, uint32_t cputime)
+{
+    struct cpu_timer *entry;
+    os_sr_t sr;
+
+    assert(timer != NULL);
+
+    /* XXX: should this use a mutex? not sure... */
+    OS_ENTER_CRITICAL(sr);
+
+    timer->cputime = cputime;
+    if (TAILQ_EMPTY(&g_cputimer_q)) {
+        TAILQ_INSERT_HEAD(&g_cputimer_q, timer, link);
+    } else {
+        TAILQ_FOREACH(entry, &g_cputimer_q, link) {
+            if ((int32_t)(timer->cputime - entry->cputime) < 0) {
+                TAILQ_INSERT_BEFORE(entry, timer, link);   
+                break;
+            }
+        }
+        if (!entry) {
+            TAILQ_INSERT_TAIL(&g_cputimer_q, timer, link);
+        }
+    }
+
+    /* If this is the head, we need to set new OCMP */
+    if (timer == TAILQ_FIRST(&g_cputimer_q)) {
+        cputime_set_ocmp(timer);
+    }
+
+    OS_EXIT_CRITICAL(sr);
+}
+
+/**
+ * cputimer timer relative 
+ *  
+ * Sets a cpu timer that will expire 'usecs' microseconds from the current 
+ * cputime. 
+ * 
+ * @param timer Pointer to timer. Cannot be NULL.
+ * @param usecs The number of usecs from now at which the timer will expire.
+ */
+void 
+cputime_timer_relative(struct cpu_timer *timer, uint32_t usecs)
+{
+    uint32_t cputime;
+
+    assert(timer != NULL);
+
+    cputime = cputime_get32() + cputime_usecs_to_ticks(usecs);
+    cputime_timer_start(timer, cputime);
+}
+
+/**
+ * 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 running. 
+ * 
+ * @param timer Pointer to cputimer to stop. Cannot be NULL.
+ */
+void 
+cputime_timer_stop(struct cpu_timer *timer)
+{
+    os_sr_t sr;
+    int reset_ocmp;
+    struct cpu_timer *entry;
+
+    assert(timer != NULL);
+
+    OS_ENTER_CRITICAL(sr);
+
+    /* If first on queue, we will need to reset OCMP */
+    if (timer->link.tqe_prev != NULL) {
+        reset_ocmp = 0;
+        if (timer == TAILQ_FIRST(&g_cputimer_q)) {
+            entry = TAILQ_NEXT(timer, link);
+            reset_ocmp = 1;
+        }
+        TAILQ_REMOVE(&g_cputimer_q, timer, link);
+        if (reset_ocmp) {
+            if (entry) {
+                cputime_set_ocmp(entry);
+            } else {
+                os_callout_stop(&g_native_cputimer.cf_c);
+            }
+        }
+    }
+
+    OS_EXIT_CRITICAL(sr);
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/mcu/native/src/hal_flash.c
----------------------------------------------------------------------
diff --git a/hw/mcu/native/src/hal_flash.c b/hw/mcu/native/src/hal_flash.c
index 63f3645..98eb6df 100644
--- a/hw/mcu/native/src/hal_flash.c
+++ b/hw/mcu/native/src/hal_flash.c
@@ -4,7 +4,7 @@
  * Licensed 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
@@ -14,79 +14,97 @@
  * limitations under the License.
  */
 
-#include <stdio.h>
+#include <sys/mman.h>
+#include <fcntl.h>
 #include <assert.h>
 #include <string.h>
 #include <inttypes.h>
-#include "hal/hal_flash.h"
-
-static FILE *file;
-
-static const struct flash_area_desc {
-    uint32_t fad_offset;
-    uint32_t fad_length;
-    uint32_t fad_sector_id;
-} flash_area_descs[] = {
-    { 0x00000000, 16 * 1024,  0 },
-    { 0x00004000, 16 * 1024,  1 },
-    { 0x00008000, 16 * 1024,  2 },
-    { 0x0000c000, 16 * 1024,  3 },
-    { 0x00010000, 64 * 1024,  4 },
-    { 0x00020000, 128 * 1024, 5 },
-    { 0x00040000, 128 * 1024, 6 },
-    { 0x00060000, 128 * 1024, 7 },
-    { 0x00080000, 128 * 1024, 8 },
-    { 0x000a0000, 128 * 1024, 9 },
-    { 0x000c0000, 128 * 1024, 10 },
-    { 0x000e0000, 128 * 1024, 11 },
+#include <stdlib.h>
+#include "hal/hal_flash_int.h"
+#include "mcu/mcu_sim.h"
+
+char *native_flash_file;
+static int file;
+static void *file_loc;
+
+static int native_flash_init(void);
+static int native_flash_read(uint32_t address, void *dst, uint32_t length);
+static int native_flash_write(uint32_t address, const void *src,
+  uint32_t length);
+static int native_flash_erase_sector(uint32_t sector_address);
+static int native_flash_sector_info(int idx, uint32_t *address, uint32_t *size);
+
+static const struct hal_flash_funcs native_flash_funcs = {
+    .hff_read = native_flash_read,
+    .hff_write = native_flash_write,
+    .hff_erase_sector = native_flash_erase_sector,
+    .hff_sector_info = native_flash_sector_info,
+    .hff_init = native_flash_init
+};
+
+static const uint32_t native_flash_sectors[] = {
+    0x00000000, /* 16 * 1024 */
+    0x00004000, /* 16 * 1024 */
+    0x00008000, /* 16 * 1024 */
+    0x0000c000, /* 16 * 1024 */
+    0x00010000, /* 64 * 1024 */
+    0x00020000, /* 128 * 1024 */
+    0x00040000, /* 128 * 1024 */
+    0x00060000, /* 128 * 1024 */
+    0x00080000, /* 128 * 1024 */
+    0x000a0000, /* 128 * 1024 */
+    0x000c0000, /* 128 * 1024 */
+    0x000e0000, /* 128 * 1024 */
 };
 
-#define FLASH_NUM_AREAS   (int)(sizeof flash_area_descs /       \
-                                sizeof flash_area_descs[0])
+#define FLASH_NUM_AREAS   (int)(sizeof native_flash_sectors /           \
+                                sizeof native_flash_sectors[0])
+
+const struct hal_flash native_flash_dev = {
+    .hf_itf = &native_flash_funcs,
+    .hf_base_addr = 0,
+    .hf_size = 1024 * 1024,
+    .hf_sector_cnt = FLASH_NUM_AREAS,
+};
 
 static void
 flash_native_erase(uint32_t addr, uint32_t len)
 {
-    static uint8_t buf[256];
-    uint32_t end;
-    int chunk_sz;
-    int rc;
-
-    end = addr + len;
-    memset(buf, 0xff, sizeof buf);
+    memset(file_loc + addr, 0xff, len);
+}
 
-    rc = fseek(file, addr, SEEK_SET);
-    assert(rc == 0);
+static void
+flash_native_file_open(char *name)
+{
+    int created = 0;
+    extern char *tmpnam(char *s);
+    extern int ftruncate(int fd, off_t length);
 
-    while (addr < end) {
-        if (end - addr < sizeof buf) {
-            chunk_sz = end - addr;
-        } else {
-            chunk_sz = sizeof buf;
+    if (!name) {
+        name = tmpnam(NULL);
+    }
+    file = open(name, O_RDWR);
+    if (file < 0) {
+        file = open(name, O_RDWR | O_CREAT);
+        assert(file > 0);
+        created = 1;
+        if (ftruncate(file, native_flash_dev.hf_size) < 0) {
+            assert(0);
         }
-        rc = fwrite(buf, chunk_sz, 1, file);
-        assert(rc == 1);
-
-        addr += chunk_sz;
     }
-    fflush(file);
+    file_loc = mmap(0, native_flash_dev.hf_size,
+          PROT_READ | PROT_WRITE, MAP_SHARED, file, 0);
+    assert(file_loc != MAP_FAILED);
+    if (created) {
+        flash_native_erase(0, native_flash_dev.hf_size);
+    }
 }
 
 static void
 flash_native_ensure_file_open(void)
 {
-    int expected_sz;
-    int i;
-
-    if (file == NULL) {
-        expected_sz = 0;
-        for (i = 0; i < FLASH_NUM_AREAS; i++) {
-            expected_sz += flash_area_descs[i].fad_length;
-        }
-
-        file = tmpfile();
-        assert(file != NULL);
-        flash_native_erase(0, expected_sz);
+    if (file == 0) {
+        flash_native_file_open(NULL);
     }
 }
 
@@ -109,8 +127,6 @@ flash_native_write_internal(uint32_t address, const void *src, uint32_t length,
 
     flash_native_ensure_file_open();
 
-    fseek(file, address, SEEK_SET);
-
     cur = address;
     while (cur < end) {
         if (end - cur < sizeof buf) {
@@ -121,7 +137,7 @@ flash_native_write_internal(uint32_t address, const void *src, uint32_t length,
 
         /* Ensure data is not being overwritten. */
         if (!allow_overwrite) {
-            rc = flash_read(cur, buf, chunk_sz);
+            rc = native_flash_read(cur, buf, chunk_sz);
             assert(rc == 0);
             for (i = 0; i < chunk_sz; i++) {
                 assert(buf[i] == 0xff);
@@ -131,60 +147,29 @@ flash_native_write_internal(uint32_t address, const void *src, uint32_t length,
         cur += chunk_sz;
     }
 
-    fseek(file, address, SEEK_SET);
-    rc = fwrite(src, length, 1, file);
-    assert(rc == 1);
+    memcpy((char *)file_loc + address, src, length);
 
-    fflush(file);
     return 0;
 }
 
-int
-flash_write(uint32_t address, const void *src, uint32_t length)
+static int
+native_flash_write(uint32_t address, const void *src, uint32_t length)
 {
     return flash_native_write_internal(address, src, length, 0);
 }
 
 int
-flash_native_overwrite(uint32_t address, const void *src, uint32_t length)
-{
-    return flash_native_write_internal(address, src, length, 1);
-}
-
-int
 flash_native_memset(uint32_t offset, uint8_t c, uint32_t len)
 {
-    uint8_t buf[256];
-    int chunk_sz;
-    int rc;
-
-    memset(buf, c, sizeof buf);
-
-    while (len > 0) {
-        if (len > sizeof buf) {
-            chunk_sz = sizeof buf;
-        } else {
-            chunk_sz = len;
-        }
-
-        rc = flash_native_overwrite(offset, buf, chunk_sz);
-        if (rc != 0) {
-            return rc;
-        }
-
-        offset += chunk_sz;
-        len -= chunk_sz;
-    }
-
+    memset(file_loc + offset, c, len);
     return 0;
 }
 
-int
-flash_read(uint32_t address, void *dst, uint32_t length)
+static int
+native_flash_read(uint32_t address, void *dst, uint32_t length)
 {
     flash_native_ensure_file_open();
-    fseek(file, address, SEEK_SET);
-    fread(dst, length, 1, file);
+    memcpy(dst, (char *)file_loc + address, length);
 
     return 0;
 }
@@ -195,7 +180,7 @@ find_area(uint32_t address)
     int i;
 
     for (i = 0; i < FLASH_NUM_AREAS; i++) {
-        if (flash_area_descs[i].fad_offset == address) {
+        if (native_flash_sectors[i] == address) {
             return i;
         }
     }
@@ -203,12 +188,24 @@ find_area(uint32_t address)
     return -1;
 }
 
-int
-flash_erase_sector(uint32_t sector_address)
+static int
+flash_sector_len(int sector)
+{
+    uint32_t end;
+
+    if (sector == FLASH_NUM_AREAS - 1) {
+        end = native_flash_dev.hf_size + native_flash_sectors[0];
+    } else {
+        end = native_flash_sectors[sector + 1];
+    }
+    return end - native_flash_sectors[sector];
+}
+
+static int
+native_flash_erase_sector(uint32_t sector_address)
 {
-    int next_sector_id;
-    int sector_id;
     int area_id;
+    uint32_t len;
 
     flash_native_ensure_file_open();
 
@@ -216,59 +213,27 @@ flash_erase_sector(uint32_t sector_address)
     if (area_id == -1) {
         return -1;
     }
-
-    sector_id = flash_area_descs[area_id].fad_sector_id;
-    while (1) {
-        flash_native_erase(sector_address,
-                           flash_area_descs[area_id].fad_length);
-
-        area_id++;
-        if (area_id >= FLASH_NUM_AREAS) {
-            break;
-        }
-
-        next_sector_id = flash_area_descs[area_id].fad_sector_id;
-        if (next_sector_id != sector_id) {
-            break;
-        }
-
-        sector_id = next_sector_id;
-    }
-
+    len = flash_sector_len(area_id);
+    flash_native_erase(sector_address, len);
     return 0;
 }
 
-int
-flash_erase(uint32_t address, uint32_t num_bytes)
+static int
+native_flash_sector_info(int idx, uint32_t *address, uint32_t *size)
 {
-    const struct flash_area_desc *area;
-    uint32_t end;
-    int i;
-
-    flash_native_ensure_file_open();
-
-    end = address + num_bytes;
-
-    for (i = 0; i < FLASH_NUM_AREAS; i++) {
-        area = flash_area_descs + i;
-
-        if (area->fad_offset >= end) {
-            return 0;
-        }
-
-        if (address >= area->fad_offset &&
-            address < area->fad_offset + area->fad_length) {
-
-            flash_native_erase(area->fad_offset, area->fad_length);
-        }
-    }
+    assert(idx < FLASH_NUM_AREAS);
 
+    *address = native_flash_sectors[idx];
+    *size = flash_sector_len(idx);
     return 0;
 }
 
-int
-flash_init(void)
+static int
+native_flash_init(void)
 {
+    if (native_flash_file) {
+        flash_native_file_open(native_flash_file);
+    }
     return 0;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/mcu/native/src/hal_gpio.c
----------------------------------------------------------------------
diff --git a/hw/mcu/native/src/hal_gpio.c b/hw/mcu/native/src/hal_gpio.c
index 5e864de..98f7c8c 100644
--- a/hw/mcu/native/src/hal_gpio.c
+++ b/hw/mcu/native/src/hal_gpio.c
@@ -78,7 +78,6 @@ void gpio_write(int pin, int val)
         return;
     }
     hal_gpio[pin].val = (val != 0);
-    printf("GPIO %d is now %d\n", pin, val);
 }
 
 int

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/mcu/native/src/hal_system.c
----------------------------------------------------------------------
diff --git a/hw/mcu/native/src/hal_system.c b/hw/mcu/native/src/hal_system.c
index 00a981e..eb64b60 100644
--- a/hw/mcu/native/src/hal_system.c
+++ b/hw/mcu/native/src/hal_system.c
@@ -4,7 +4,7 @@
  * Licensed 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
@@ -13,9 +13,54 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
 
 #include "hal/hal_system.h"
+#include "mcu/mcu_sim.h"
 
 void
 system_reset(void)
-{ }
+{
+    while(1);
+}
+
+/*
+ * When running projects within simulator, it's useful to be able to
+ * pass operating info as parameters to simulator program.
+ * This routine is meant to parse those.
+ */
+static void
+usage(char *progname, int rc)
+{
+    const char msg[] =
+      "Usage: %s [-f flash_file]\n"
+      "     -f flash_file tells where binary flash file is located. It gets\n"
+      "        created if it doesn't already exist.\n";
+
+    write(2, msg, strlen(msg));
+    exit(rc);
+}
+
+void
+mcu_sim_parse_args(int argc, char **argv)
+{
+    int ch;
+    char *progname = argv[0];
+
+    while ((ch = getopt(argc, argv, "hf:")) != -1) {
+        switch (ch) {
+        case 'f':
+            native_flash_file = optarg;
+            break;
+        case 'h':
+            usage(progname, 0);
+            break;
+        default:
+            usage(progname, -1);
+            break;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/hw/mcu/native/src/hal_uart.c
----------------------------------------------------------------------
diff --git a/hw/mcu/native/src/hal_uart.c b/hw/mcu/native/src/hal_uart.c
index dd1d6a8..2f66016 100644
--- a/hw/mcu/native/src/hal_uart.c
+++ b/hw/mcu/native/src/hal_uart.c
@@ -18,14 +18,20 @@
 #include "hal/hal_uart.h"
 #include "bsp/bsp.h"
 
+#ifdef MN_LINUX
+#include <pty.h>
+#endif
+#ifdef MN_OSX
 #include <util.h>
+#endif
+#include <stdio.h>
 #include <fcntl.h>
 #include <assert.h>
 #include <unistd.h>
 #include <string.h>
 
 #define UART_MAX_BYTES_PER_POLL	64
-#define UART_POLLER_STACK_SZ	1024
+#define UART_POLLER_STACK_SZ	(1024)
 #define UART_POLLER_PRIO	0
 
 struct uart {
@@ -117,23 +123,33 @@ uart_poller(void *arg)
     }
 }
 
-static int
-uart_pty(void)
+static void
+set_nonblock(int fd)
 {
-    int fd;
-    int loop_slave;
     int flags;
-    struct termios tios;
-    char pty_name[32];
 
-    if (openpty(&fd, &loop_slave, pty_name, NULL, NULL) < 0) {
-        perror("openpty() failed");
-        return -1;
+    flags = fcntl(fd, F_GETFL);
+    if (flags == -1) {
+        const char msg[] = "fcntl(F_GETFL) fail";
+        write(1, msg, sizeof(msg));
+        return;
+    }
+    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+        const char msg[] = "fcntl(F_SETFL) fail";
+        write(1, msg, sizeof(msg));
+        return;
     }
+}
 
-    if (tcgetattr(loop_slave, &tios)) {
-        perror("tcgetattr() failed");
-        goto err;
+static int
+uart_set_attr(int fd)
+{
+    struct termios tios;
+
+    if (tcgetattr(fd, &tios)) {
+        const char msg[] = "tcgetattr() failed";
+        write(1, msg, sizeof(msg));
+        return -1;
     }
 
     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
@@ -141,22 +157,34 @@ uart_pty(void)
     tios.c_iflag = IGNPAR | IXON;
     tios.c_oflag = 0;
     tios.c_lflag = 0;
-    if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0) {
-        perror("tcsetattr() failed");
-        goto err;
+    if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
+        const char msg[] = "tcsetattr() failed";
+        write(1, msg, sizeof(msg));
+        return -1;
     }
+    return 0;
+}
 
-    flags = fcntl(fd, F_GETFL);
-    if (flags == -1) {
-        perror("fcntl(F_GETFL) fail");
-        goto err;
+static int
+uart_pty(int port)
+{
+    int fd;
+    int loop_slave;
+    char pty_name[32];
+    char msg[64];
+
+    if (openpty(&fd, &loop_slave, pty_name, NULL, NULL) < 0) {
+        const char msg[] = "openpty() failed";
+        write(1, msg, sizeof(msg));
+        return -1;
     }
-    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
-        perror("fcntl(F_SETFL) fail");
+
+    if (uart_set_attr(loop_slave)) {
         goto err;
     }
 
-    printf("console at %s\n", pty_name);
+    snprintf(msg, sizeof(msg), "uart%d at %s\n", port, pty_name);
+    write(1, msg, strlen(msg));
     return fd;
 err:
     close(fd);
@@ -183,6 +211,17 @@ hal_uart_start_rx(int port)
     /* nothing to do here */
 }
 
+void
+hal_uart_blocking_tx(int port, uint8_t data)
+{
+    if (port >= UART_CNT || uarts[port].u_open == 0) {
+        return;
+    }
+
+    /* XXX: Count statistics and add error checking here. */
+    (void) write(uarts[port].u_fd, &data, sizeof(data));
+}
+
 int
 hal_uart_init_cbs(int port, hal_uart_tx_char tx_func, hal_uart_tx_done tx_done,
   hal_uart_rx_char rx_func, void *arg)
@@ -228,10 +267,13 @@ hal_uart_config(int port, int32_t baudrate, uint8_t databits, uint8_t stopbits,
     if (uart->u_open) {
         return -1;
     }
-    uart->u_fd = uart_pty();
+
+    uart->u_fd = uart_pty(port);
     if (uart->u_fd < 0) {
         return -1;
     }
+    set_nonblock(uart->u_fd);
+
     uart->u_open = 1;
     return 0;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/egg.yml
----------------------------------------------------------------------
diff --git a/libs/os/egg.yml b/libs/os/egg.yml
index c8bd535..08c4413 100644
--- a/libs/os/egg.yml
+++ b/libs/os/egg.yml
@@ -2,3 +2,13 @@ egg.name: libs/os
 egg.vers: 0.1 
 egg.deps:
     - libs/testutil
+egg.req_caps:
+    - console
+
+egg.deps.SHELL:
+    - libs/console/full 
+    - libs/shell 
+egg.cflags.SHELL: -DSHELL_PRESENT 
+
+# Satisfy capability dependencies for the self-contained test executable.
+egg.deps.selftest: libs/console/stub

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/include/os/arch/cortex_m4/os/os_arch.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/arch/cortex_m4/os/os_arch.h b/libs/os/include/os/arch/cortex_m4/os/os_arch.h
index b6e0006..1d6bd13 100755
--- a/libs/os/include/os/arch/cortex_m4/os/os_arch.h
+++ b/libs/os/include/os/arch/cortex_m4/os/os_arch.h
@@ -57,9 +57,6 @@ typedef uint32_t os_stack_t;
 #define sec_bss_core    __attribute__((section(".bss.core")))
 #define sec_bss_nz_core __attribute__((section(".bss.core.nz")))
 
-/* Define "assert" funtion */
-void _Die(char *file, int line);
-
 os_stack_t *os_arch_task_stack_init(struct os_task *, os_stack_t *, int);
 void timer_handler(void);
 void os_arch_ctx_sw(struct os_task *);
@@ -72,6 +69,7 @@ os_error_t os_arch_os_init(void);
 os_error_t os_arch_os_start(void);
 void os_set_env(void);
 void os_arch_init_task_stack(os_stack_t *sf);
+void os_default_irq_asm(void);
 
 /* External function prototypes supplied by BSP */
 void os_bsp_systick_init(uint32_t os_tick_usecs);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/include/os/arch/sim/os/os_arch.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/arch/sim/os/os_arch.h b/libs/os/include/os/arch/sim/os/os_arch.h
index 7144a44..3466727 100644
--- a/libs/os/include/os/arch/sim/os/os_arch.h
+++ b/libs/os/include/os/arch/sim/os/os_arch.h
@@ -60,4 +60,6 @@ void os_arch_restore_sr(int);
 os_error_t os_arch_os_init(void);
 os_error_t os_arch_os_start(void);
 
+void os_bsp_init(void);
+
 #endif /* _OS_ARCH_SIM_H */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/include/os/os.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os.h b/libs/os/include/os/os.h
index 62b4c11..938f8b7 100644
--- a/libs/os/include/os/os.h
+++ b/libs/os/include/os/os.h
@@ -43,6 +43,8 @@
  */
 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.
@@ -84,6 +86,7 @@ void os_init_idle_task(void);
 #include "os/os_sched.h"
 #include "os/os_eventq.h"
 #include "os/os_callout.h" 
+#include "os/os_heap.h"
 #include "os/os_mutex.h"
 #include "os/os_sem.h"
 #include "os/os_mempool.h"

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/include/os/os_eventq.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os_eventq.h b/libs/os/include/os/os_eventq.h
index 56dc436..4abdea4 100644
--- a/libs/os/include/os/os_eventq.h
+++ b/libs/os/include/os/os_eventq.h
@@ -17,6 +17,8 @@
 #ifndef _OS_EVENTQ_H
 #define _OS_EVENTQ_H
 
+#include <inttypes.h>
+
 struct os_event {
     uint8_t ev_queued;
     uint8_t ev_type;
@@ -27,6 +29,7 @@ struct os_event {
 #define OS_EVENT_QUEUED(__ev) ((__ev)->ev_queued)
 
 #define OS_EVENT_T_TIMER (1)
+#define OS_EVENT_T_MQUEUE_DATA (2) 
 #define OS_EVENT_T_PERUSER (16)
 
 struct os_eventq {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/include/os/os_mbuf.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os_mbuf.h b/libs/os/include/os/os_mbuf.h
index 9cb26f6..881ddba 100644
--- a/libs/os/include/os/os_mbuf.h
+++ b/libs/os/include/os/os_mbuf.h
@@ -17,11 +17,14 @@
 #ifndef _OS_MBUF_H 
 #define _OS_MBUF_H 
 
+#include "os/os_eventq.h"
 
 /**
- * A mbuf pool to allocate a mbufs out of.  This contains a pointer to the 
- * mempool to allocate mbufs out of, along with convenient housekeeping 
- * information on mbufs in the pool (e.g. length of variable packet header)
+ * 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 {
     /** 
@@ -34,10 +37,6 @@ struct os_mbuf_pool {
      */
     uint16_t omp_mbuf_count;
     /**
-     * The length of the variable portion of the mbuf header
-     */
-    uint16_t omp_hdr_len;
-    /**
      * The memory pool which to allocate mbufs out of 
      */
     struct os_mempool *omp_pool;
@@ -51,7 +50,11 @@ struct os_mbuf_pkthdr {
     /**
      * Overall length of the packet. 
      */
-    uint32_t omp_len;
+    uint16_t omp_len;
+    /**
+     * Flags
+     */
+    uint16_t omp_flags;
     /**
      * Next packet in the mbuf chain.
      */
@@ -69,13 +72,22 @@ struct os_mbuf {
     /**
      * Flags associated with this buffer, see OS_MBUF_F_* defintions
      */
-    uint16_t om_flags;
+    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;
@@ -86,15 +98,10 @@ struct os_mbuf {
     uint8_t om_databuf[0];
 };
 
-/*
- * Mbuf flags: 
- *  - OS_MBUF_F_PKTHDR: Whether or not this mbuf is a packet header mbuf
- *  - OS_MBUF_F_USER: The base user defined mbuf flag, start defining your 
- *    own flags from this flag number.
- */
-
-#define OS_MBUF_F_PKTHDR (0)
-#define OS_MBUF_F_USER   (OS_MBUF_F_PKTHDR + 1) 
+struct os_mqueue {
+    STAILQ_HEAD(, os_mbuf_pkthdr) mq_head;
+    struct os_event mq_ev;
+};
 
 /*
  * Given a flag number, provide the mask for it
@@ -109,12 +116,16 @@ struct os_mbuf {
  * @param __om The mbuf to check 
  */
 #define OS_MBUF_IS_PKTHDR(__om) \
-    ((__om)->om_flags & OS_MBUF_F_MASK(OS_MBUF_F_PKTHDR))
-
+    ((__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))
+
 /*
  * Access the data of a mbuf, and cast it to type
  *
@@ -124,31 +135,19 @@ struct os_mbuf {
 #define OS_MBUF_DATA(__om, __type) \
      (__type) ((__om)->om_data)
 
-/**
- * Returns the end offset of a mbuf buffer 
- * 
- * @param __omp 
- */
-#define OS_MBUF_END_OFF(__omp) ((__omp)->omp_databuf_len)
-
-/**
- * Returns the start offset of a mbuf buffer
- */
-#define OS_MBUF_START_OFF(__omp) (0)
-
 
 /*
  * Called by OS_MBUF_LEADINGSPACE() macro
  */
 static inline uint16_t 
-_os_mbuf_leadingspace(struct os_mbuf_pool *omp, struct os_mbuf *om)
+_os_mbuf_leadingspace(struct os_mbuf *om)
 {
     uint16_t startoff;
     uint16_t leadingspace;
 
     startoff = 0;
     if (OS_MBUF_IS_PKTHDR(om)) {
-        startoff = sizeof(struct os_mbuf_pkthdr) + omp->omp_hdr_len;
+        startoff = om->om_pkthdr_len;
     }
 
     leadingspace = (uint16_t) (OS_MBUF_DATA(om, uint8_t *) - 
@@ -167,12 +166,16 @@ _os_mbuf_leadingspace(struct os_mbuf_pool *omp, struct os_mbuf *om)
  *
  * @return Amount of leading space available in the mbuf 
  */
-#define OS_MBUF_LEADINGSPACE(__omp, __om) _os_mbuf_leadingspace(__omp, __om)
+#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_pool *omp, struct os_mbuf *om)
+_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;
 }
 
@@ -185,30 +188,54 @@ _os_mbuf_trailingspace(struct os_mbuf_pool *omp, struct os_mbuf *om)
  *
  * @return The amount of trailing space available in the mbuf 
  */
-#define OS_MBUF_TRAILINGSPACE(__omp, __om) _os_mbuf_trailingspace(__omp, __om)
+#define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om)
 
+/* Mbuf queue functions */
+
+/* Initialize a mbuf queue */
+int os_mqueue_init(struct os_mqueue *, 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 *);
 
 /* Initialize a mbuf pool */
-int os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp, uint16_t, 
+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);
+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_pool *omp, struct os_mbuf *m);
+struct os_mbuf *os_mbuf_dup(struct os_mbuf *m);
+
+struct os_mbuf * os_mbuf_off(struct os_mbuf *om, int off, int *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_pool *omp, struct os_mbuf *m, void *, 
-        uint16_t);
+int os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
 
 /* Free a mbuf */
-int os_mbuf_free(struct os_mbuf_pool *omp, struct os_mbuf *mb);
+int os_mbuf_free(struct os_mbuf *mb);
 
 /* Free a mbuf chain */
-int os_mbuf_free_chain(struct os_mbuf_pool *omp, struct os_mbuf *om);
+int os_mbuf_free_chain(struct os_mbuf *om);
+
+void os_mbuf_adj(struct os_mbuf *mp, int req_len);
+int os_mbuf_memcmp(const struct os_mbuf *om, int off, const void *data,
+                   int len);
+
+struct os_mbuf *os_mbuf_prepend(struct os_mbuf *om, int 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);
 
 #endif /* _OS_MBUF_H */ 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/include/os/os_sched.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os_sched.h b/libs/os/include/os/os_sched.h
index ee84f76..a34c5e3 100644
--- a/libs/os/include/os/os_sched.h
+++ b/libs/os/include/os/os_sched.h
@@ -19,6 +19,10 @@
 
 #include "os/os_task.h"
 
+typedef int (*os_sched_walk_func_t)(struct os_task *, void *arg);
+
+int os_sched_walk(os_sched_walk_func_t walk_func, void *arg);
+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);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/include/os/os_task.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os_task.h b/libs/os/include/os/os_task.h
index 8f7c746..3f75432 100644
--- a/libs/os/include/os/os_task.h
+++ b/libs/os/include/os/os_task.h
@@ -47,7 +47,8 @@ struct os_task {
 
     uint8_t t_taskid;
     uint8_t t_prio;
-    uint8_t t_pad[2];
+    uint8_t t_state;
+    uint8_t t_pad;
 
     char *t_name;
     os_task_func_t t_func;
@@ -57,8 +58,9 @@ struct os_task {
 
     struct os_sanity_check t_sanity_check; 
 
-    os_task_state_t t_state;
     os_time_t t_next_wakeup;
+    os_time_t t_run_time;
+    uint32_t t_ctx_sw_cnt;
     
     /* Used to chain task to either the run or sleep list */ 
     TAILQ_ENTRY(os_task) t_os_list;
@@ -71,6 +73,7 @@ int os_task_init(struct os_task *, char *, os_task_func_t, void *, uint8_t,
         os_time_t, os_stack_t *, uint16_t);
 
 int os_task_sanity_checkin(struct os_task *);
+uint8_t os_task_count(void);
 
 
 #endif /* _OS_TASK_H */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/include/os/os_time.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os_time.h b/libs/os/include/os/os_time.h
index d934a68..9c2bc23 100644
--- a/libs/os/include/os/os_time.h
+++ b/libs/os/include/os/os_time.h
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
-#ifndef _OS_TIME_H 
-#define _OS_TIME_H 
+#ifndef _OS_TIME_H
+#define _OS_TIME_H
+
+#include <stdint.h>
 
 typedef uint32_t os_time_t;
 
@@ -34,5 +36,4 @@ void os_time_delay(int32_t osticks);
 #define OS_TIME_TICK_GT(__t1, __t2) ((int32_t) ((__t1) - (__t2)) > 0)
 #define OS_TIME_TICK_GEQ(__t1, __t2) ((int32_t) ((__t1) - (__t2)) >= 0)
 
-
 #endif /* _OS_TIME_H */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/src/arch/cortex_m4/m4/HAL_CM4.s
----------------------------------------------------------------------
diff --git a/libs/os/src/arch/cortex_m4/m4/HAL_CM4.s b/libs/os/src/arch/cortex_m4/m4/HAL_CM4.s
index 1c5651d..dcde207 100755
--- a/libs/os/src/arch/cortex_m4/m4/HAL_CM4.s
+++ b/libs/os/src/arch/cortex_m4/m4/HAL_CM4.s
@@ -201,6 +201,36 @@ SysTick_Handler:
         .fnend
         .size   SysTick_Handler, .-SysTick_Handler
 
+        .thumb_func
+        .type   os_default_irq_asm, %function
+        .global os_default_irq_asm
+os_default_irq_asm:
+        .fnstart
+        .cantunwind
+
+        /*
+         * LR = 0xfffffff9 if we were using MSP as SP
+         * LR = 0xfffffffd if we were using PSP as SP
+         */
+        TST     LR,#4
+        ITE     EQ
+        MRSEQ   R3,MSP
+        MRSNE   R3,PSP
+        PUSH    {R3-R11,LR}
+        MOV     R0, SP
+        BL      os_default_irq
+        POP     {R3-R11,LR}                 /* Restore EXC_RETURN */
+        BX      LR
+
+        .fnend
+        .size   os_default_irq_asm, .-os_default_irq_asm
+
+	/*
+	 * Prevent libgcc unwind stuff from getting pulled in.
+	 */
+        .section ".data"
+	.global __aeabi_unwind_cpp_pr0
+__aeabi_unwind_cpp_pr0:
         .end
 
 /*----------------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/src/arch/cortex_m4/os_arch_arm.c
----------------------------------------------------------------------
diff --git a/libs/os/src/arch/cortex_m4/os_arch_arm.c b/libs/os/src/arch/cortex_m4/os_arch_arm.c
index fc69a91..d941809 100755
--- a/libs/os/src/arch/cortex_m4/os_arch_arm.c
+++ b/libs/os/src/arch/cortex_m4/os_arch_arm.c
@@ -17,6 +17,8 @@
 #include "os/os.h"
 #include "os/os_arch.h"
 
+#include <bsp/cmsis_nvic.h>
+
 /* Initial program status register */
 #define INITIAL_xPSR    0x01000000
 
@@ -50,9 +52,6 @@ struct stack_frame {
     uint32_t    xpsr;
 };
 
-int     die_line;
-char    *die_module;
-
 #define SVC_ArgN(n) \
   register int __r##n __asm("r"#n);
 
@@ -100,6 +99,8 @@ timer_handler(void)
 void
 os_arch_ctx_sw(struct os_task *t)
 {
+    os_sched_ctx_sw_hook(t);
+
     /* Set PendSV interrupt pending bit to force context switch */
     SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
 }
@@ -107,6 +108,8 @@ os_arch_ctx_sw(struct os_task *t)
 void
 os_arch_ctx_sw_isr(struct os_task *t)
 {
+    os_sched_ctx_sw_hook(t);
+
     /* Set PendSV interrupt pending bit to force context switch */
     SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
 }
@@ -129,15 +132,6 @@ os_arch_restore_sr(os_sr_t isr_ctx)
     }
 }
 
-void
-_Die(char *file, int line)
-{
-    die_line = line;
-    die_module = file;
-    while (1) {
-    }
-}
-
 os_stack_t *
 os_arch_task_stack_init(struct os_task *t, os_stack_t *stack_top, int size)
 {
@@ -168,6 +162,10 @@ os_arch_task_stack_init(struct os_task *t, os_stack_t *stack_top, int size)
 void
 os_arch_init(void)
 {
+    /*
+     * Trap on divide-by-zero.
+     */
+    SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;
     os_init_idle_task();
 }
 
@@ -195,6 +193,19 @@ os_arch_os_init(void)
             NVIC->IP[i] = 0xff;
         }
 
+        /*
+         * Install default interrupt handler, which'll print out system
+         * state at the time of the interrupt, and few other regs which
+         * should help in trying to figure out what went wrong.
+         */
+        NVIC_SetVector(-13, (uint32_t)os_default_irq_asm); /* Hardfault */
+        NVIC_SetVector(MemoryManagement_IRQn, (uint32_t)os_default_irq_asm);
+        NVIC_SetVector(BusFault_IRQn, (uint32_t)os_default_irq_asm);
+        NVIC_SetVector(UsageFault_IRQn, (uint32_t)os_default_irq_asm);
+        for (i = 0; i < NVIC_NUM_VECTORS - NVIC_USER_IRQ_OFFSET; i++) {
+            NVIC_SetVector(i, (uint32_t)os_default_irq_asm);
+        }
+
         /* Call bsp related OS initializations */
         os_bsp_init();
 
@@ -224,9 +235,9 @@ os_arch_os_init(void)
 
 /**
  * os systick init
- *  
+ *
  * Initializes systick for the MCU
- * 
+ *
  * @param os_tick_usecs The number of microseconds in an os time tick
  */
 static void
@@ -283,7 +294,7 @@ os_arch_os_start(void)
 
     err = OS_ERR_IN_ISR;
     if (__get_IPSR() == 0) {
-        /* 
+        /*
          * The following switch statement is really just a sanity check to
          * insure that the os initialization routine was called prior to the
          * os start routine.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/src/arch/cortex_m4/os_fault.c
----------------------------------------------------------------------
diff --git a/libs/os/src/arch/cortex_m4/os_fault.c b/libs/os/src/arch/cortex_m4/os_fault.c
new file mode 100644
index 0000000..2c7c6fb
--- /dev/null
+++ b/libs/os/src/arch/cortex_m4/os_fault.c
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <console/console.h>
+#include <hal/hal_system.h>
+#include "os/os.h"
+
+#include <stdint.h>
+#include <unistd.h>
+
+int             os_die_line;
+const char     *os_die_module;
+
+void __assert_func(const char *file, int line, const char *func, const char *e);
+
+void
+__assert_func(const char *file, int line, const char *func, const char *e)
+{
+    int sr;
+
+    OS_ENTER_CRITICAL(sr);
+    (void)sr;
+    os_die_line = line;
+    os_die_module = file;
+    console_blocking_mode();
+    console_printf("Assert %s; failed in %s:%d\n", e ? e : "", file, line);
+    system_reset();
+}
+
+struct exception_frame {
+    uint32_t r0;
+    uint32_t r1;
+    uint32_t r2;
+    uint32_t r3;
+    uint32_t r12;
+    uint32_t lr;
+    uint32_t pc;
+    uint32_t psr;
+};
+
+struct trap_frame {
+    struct exception_frame *ef;
+    uint32_t sp;
+    uint32_t r4;
+    uint32_t r5;
+    uint32_t r6;
+    uint32_t r7;
+    uint32_t r8;
+    uint32_t r9;
+    uint32_t r10;
+    uint32_t r11;
+};
+
+void
+os_default_irq(struct trap_frame *tf)
+{
+    console_blocking_mode();
+    console_printf("Unhandled interrupt (%d), exception sp 0x%08x\n",
+      SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk, (uint32_t)tf->ef);
+    console_printf(" r0:0x%08x  r1:0x%08x  r2:0x%08x  r3:0x%08x\n",
+      tf->ef->r0, tf->ef->r1, tf->ef->r2, tf->ef->r3);
+    console_printf(" r4:0x%08x  r5:0x%08x  r6:0x%08x  r7:0x%08x\n",
+      tf->r4, tf->r5, tf->r6, tf->r7);
+    console_printf(" r8:0x%08x  r9:0x%08x r10:0x%08x r11:0x%08x\n",
+      tf->r8, tf->r9, tf->r10, tf->r11);
+    console_printf("r12:0x%08x  lr:0x%08x  pc:0x%08x psr:0x%08x\n",
+      tf->ef->r12, tf->ef->lr, tf->ef->pc, tf->ef->psr);
+    console_printf("ICSR:0x%08x HFSR:0x%08x CFSR:0x%08x\n",
+      SCB->ICSR, SCB->HFSR, SCB->CFSR);
+    console_printf("BFAR:0x%08x MMFAR:0x%08x\n", SCB->BFAR, SCB->MMFAR);
+    system_reset();
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/src/arch/sim/os_arch_sim.c
----------------------------------------------------------------------
diff --git a/libs/os/src/arch/sim/os_arch_sim.c b/libs/os/src/arch/sim/os_arch_sim.c
index 5d2bfe6..0c83487 100644
--- a/libs/os/src/arch/sim/os_arch_sim.c
+++ b/libs/os/src/arch/sim/os_arch_sim.c
@@ -23,6 +23,7 @@
 
 #include <string.h>
 #include <stdio.h>
+#include <unistd.h>
 #include <setjmp.h>
 #include <signal.h>
 #include <sys/time.h>
@@ -152,6 +153,8 @@ os_arch_ctx_sw(struct os_task *next_t)
         }
     }
 
+    os_sched_ctx_sw_hook(next_t);
+
     os_sched_set_current_task(next_t);
 
     sf = (struct stack_frame *) next_t->t_stackptr;
@@ -196,6 +199,8 @@ os_arch_ctx_sw_isr(struct os_task *next_t)
 
     isr_state(&block_isr_off, NULL);
 
+    os_sched_ctx_sw_hook(next_t);
+
     os_sched_set_current_task(next_t);
     
     sf = (struct stack_frame *) next_t->t_stackptr;
@@ -294,8 +299,9 @@ start_timer(void)
 
     rc = setitimer(ITIMER_VIRTUAL, &it, NULL);
     if (rc != 0) {
-        perror("Cannot set itimer");
-        abort();
+        const char msg[] = "Cannot set itimer";
+        write(2, msg, sizeof(msg));
+        _exit(1);
     }
 }
 
@@ -308,7 +314,10 @@ os_arch_os_init(void)
     TAILQ_INIT(&g_os_sleep_list);
 
     os_init_idle_task();
-    os_sanity_task_init(); 
+    os_sanity_task_init();
+
+    os_bsp_init();
+
     return OS_OK;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/src/arch/sim/os_fault.c
----------------------------------------------------------------------
diff --git a/libs/os/src/arch/sim/os_fault.c b/libs/os/src/arch/sim/os_fault.c
new file mode 100644
index 0000000..8bd8fbe
--- /dev/null
+++ b/libs/os/src/arch/sim/os_fault.c
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <string.h>
+#include <unistd.h>
+
+#include "os/os.h"
+#include "os_priv.h"
+
+void
+__assert_func(const char *file, int line, const char *func, const char *e)
+{
+    char msg[256];
+
+    snprintf(msg, sizeof(msg), "assert at %s:%d\n", file, line);
+    write(1, msg, strlen(msg));
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/src/os.c
----------------------------------------------------------------------
diff --git a/libs/os/src/os.c b/libs/os/src/os.c
index 3ca3177..581db1d 100644
--- a/libs/os/src/os.c
+++ b/libs/os/src/os.c
@@ -59,6 +59,9 @@ os_init(void)
 
     err = os_arch_os_init();
     assert(err == OS_OK);
+
+    err = os_info_init();
+    assert(err == OS_OK);
 }
 
 void

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-tadpole/blob/29ce5cdc/libs/os/src/os_info.c
----------------------------------------------------------------------
diff --git a/libs/os/src/os_info.c b/libs/os/src/os_info.c
new file mode 100644
index 0000000..ebb6f12
--- /dev/null
+++ b/libs/os/src/os_info.c
@@ -0,0 +1,169 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 "console/console.h"
+#ifdef SHELL_PRESENT
+#include "shell/shell.h" 
+#endif
+
+#include <string.h>
+
+struct os_task_info_walk {
+    struct os_task_info *info;
+    int info_cnt;
+};
+
+#define OS_TASK_INFO_NAME_SIZE (32)
+struct os_task_info {
+    uint8_t oti_tid;
+    uint8_t oti_prio;
+    uint8_t oti_state;
+    uint8_t oti_pad1;
+    uint16_t oti_flags;
+    uint16_t oti_stack_size;
+    uint32_t oti_csw_cnt;
+    os_time_t oti_next_wakeup;
+    os_time_t oti_run_time;
+    char oti_name[OS_TASK_INFO_NAME_SIZE];
+};
+
+int os_task_info_get(struct os_task_info *info, int info_cnt);
+
+#ifdef SHELL_PRESENT
+struct shell_cmd shell_os_tasks_display_cmd;
+#endif
+
+
+#ifdef SHELL_PRESENT
+/* Code to register with shell, and display the results of os_getinfo() 
+ */
+
+
+int 
+shell_os_tasks_display(int argc, char **argv)
+{
+    struct os_task_info *info; 
+    char *name;
+    int i;
+    int found;
+    int rc;
+    uint8_t tcount;
+
+    name = NULL;
+    found = 0;
+
+    if (argv[1] != NULL && strcmp(argv[1], "")) {
+        name = argv[1];
+    }   
+
+    tcount = os_task_count();
+
+    info = (struct os_task_info *) os_malloc(
+            sizeof(struct os_task_info) * tcount);
+    if (!info) {
+        rc = -1;
+        goto err;
+    }
+
+    rc = os_task_info_get(info, tcount);
+
+    console_printf("%d tasks: \n", rc);
+    for (i = 0; i < rc; i++) {
+        if (name) {
+            if (strcmp(name, info[i].oti_name)) {
+                continue;
+            } else {
+                found = 1;
+            }
+        }
+
+        console_printf("  %s (prio: %u, nw: %u, flags: 0x%x, "
+                "ssize: %u, cswcnt: %lu, tot_run_time: %ums)", 
+                info[i].oti_name, 
+                info[i].oti_prio, info[i].oti_next_wakeup, info[i].oti_flags, 
+                info[i].oti_stack_size,
+                info[i].oti_csw_cnt, info[i].oti_run_time);
+
+    }
+
+    if (name && !found) {
+        console_printf("Couldn't find task with name %s\n", name);
+    }
+
+    os_free(info);
+
+    return (0);
+err:
+    return (rc);
+}
+    
+
+#endif 
+
+static int
+_os_task_copy_info(struct os_task *t, void *arg)
+{
+    struct os_task_info_walk *walk;
+
+    walk = (struct os_task_info_walk *) arg;
+
+    if (walk->info_cnt == 0) {
+        /* Stored all the elements we can fit, exit out */
+        return (1);
+    }
+
+    walk->info->oti_tid = t->t_taskid;
+    walk->info->oti_prio = t->t_prio;
+    strncpy(walk->info->oti_name, t->t_name, OS_TASK_INFO_NAME_SIZE);
+    walk->info->oti_state = (uint8_t) t->t_state;
+    walk->info->oti_next_wakeup = t->t_next_wakeup;
+    walk->info->oti_flags = t->t_flags;
+    walk->info->oti_stack_size = t->t_stacksize;
+    walk->info->oti_csw_cnt = t->t_ctx_sw_cnt;
+    walk->info->oti_run_time = t->t_run_time;
+
+    walk->info += 1;
+    walk->info_cnt--;
+
+    return (0);
+}
+
+int
+os_task_info_get(struct os_task_info *info, int info_cnt)
+{
+    struct os_task_info_walk walk;
+
+    walk.info = info;
+    walk.info_cnt = info_cnt;
+
+    os_sched_walk(_os_task_copy_info, (void *) &walk);
+    return (info_cnt - walk.info_cnt);
+}
+
+
+int 
+os_info_init(void)
+{
+#ifdef SHELL_PRESENT 
+    shell_cmd_register(&shell_os_tasks_display_cmd, "tasks", 
+            shell_os_tasks_display);
+#endif
+    return (0);
+}