Update tadpole to include the latest larva code.
diff --git a/.gitignore b/.gitignore
index b146445..2f35cd4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,10 @@
+.repo.db
+bin
+obj
+tags
+.gdb_history
+*~
.nest
+.DS_Store
+*.swp
+*.swo
diff --git a/hw/hal/include/hal/hal_flash.h b/hw/hal/include/hal/hal_flash.h
index be3b358..787e9c2 100644
--- a/hw/hal/include/hal/hal_flash.h
+++ b/hw/hal/include/hal/hal_flash.h
@@ -25,6 +25,7 @@
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);
+uint8_t hal_flash_align(uint8_t flash_id);
int hal_flash_init(void);
#endif
diff --git a/hw/hal/include/hal/hal_flash_int.h b/hw/hal/include/hal/hal_flash_int.h
index ab7e159..34cd2c4 100644
--- a/hw/hal/include/hal/hal_flash_int.h
+++ b/hw/hal/include/hal/hal_flash_int.h
@@ -34,6 +34,7 @@
uint32_t hf_base_addr;
uint32_t hf_size;
int hf_sector_cnt;
+ int hf_align; /* Alignment requirement. 1 if unrestricted. */
};
/*
diff --git a/hw/hal/include/hal/hal_spim.h b/hw/hal/include/hal/hal_spim.h
deleted file mode 100644
index fa1eeeb..0000000
--- a/hw/hal/include/hal/hal_spim.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * 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_ */
diff --git a/hw/hal/include/hal/hal_system.h b/hw/hal/include/hal/hal_system.h
index 19f5ed1..1cf43c4 100644
--- a/hw/hal/include/hal/hal_system.h
+++ b/hw/hal/include/hal/hal_system.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
@@ -17,6 +17,14 @@
#ifndef H_HAL_SYSTEM_
#define H_HAL_SYSTEM_
+/*
+ * System reset.
+ */
void system_reset(void) __attribute((noreturn));
+/*
+ * Called by bootloader to start loaded program.
+ */
+void system_start(void *img_start) __attribute((noreturn));
+
#endif
diff --git a/hw/hal/src/hal_flash.c b/hw/hal/src/hal_flash.c
index 90fd985..ef4e35a 100644
--- a/hw/hal/src/hal_flash.c
+++ b/hw/hal/src/hal_flash.c
@@ -39,6 +39,18 @@
return rc;
}
+uint8_t
+hal_flash_align(uint8_t flash_id)
+{
+ const struct hal_flash *hf;
+
+ hf = bsp_flash_dev(flash_id);
+ if (!hf) {
+ return 1;
+ }
+ return hf->hf_align;
+}
+
uint32_t
hal_flash_sector_size(const struct hal_flash *hf, int sec_idx)
{
diff --git a/hw/mcu/native/src/hal_flash.c b/hw/mcu/native/src/hal_flash.c
index 98eb6df..5fc3e6c 100644
--- a/hw/mcu/native/src/hal_flash.c
+++ b/hw/mcu/native/src/hal_flash.c
@@ -65,6 +65,7 @@
.hf_base_addr = 0,
.hf_size = 1024 * 1024,
.hf_sector_cnt = FLASH_NUM_AREAS,
+ .hf_align = 1
};
static void
@@ -85,7 +86,7 @@
}
file = open(name, O_RDWR);
if (file < 0) {
- file = open(name, O_RDWR | O_CREAT);
+ file = open(name, O_RDWR | O_CREAT, 0660);
assert(file > 0);
created = 1;
if (ftruncate(file, native_flash_dev.hf_size) < 0) {
@@ -155,6 +156,7 @@
static int
native_flash_write(uint32_t address, const void *src, uint32_t length)
{
+ assert(address % native_flash_dev.hf_align == 0);
return flash_native_write_internal(address, src, length, 0);
}
diff --git a/libs/os/include/os/endian.h b/libs/os/include/os/endian.h
new file mode 100644
index 0000000..c8c838a
--- /dev/null
+++ b/libs/os/include/os/endian.h
@@ -0,0 +1,89 @@
+/**
+ * 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_ENDIAN_
+#define H_ENDIAN_
+
+#include <inttypes.h>
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+
+#ifndef ntohll
+#define ntohll(x) ((uint64_t)(x))
+#endif
+
+#ifndef htonll
+#define htonll(x) ((uint64_t)(x))
+#endif
+
+#ifndef ntohl
+#define ntohl(x) ((uint32_t)(x))
+#endif
+
+#ifndef htonl
+#define htonl(x) ((uint32_t)(x))
+#endif
+
+#ifndef ntohs
+#define ntohs(x) ((uint16_t)(x))
+#endif
+
+#ifndef htons
+#define htons(x) ((uint16_t)(x))
+#endif
+
+#else
+
+#ifndef ntohll
+#define ntohll(x) ((uint64_t) \
+ ((((x) & 0xff00000000000000ull) >> 56) | \
+ (((x) & 0x00ff000000000000ull) >> 40) | \
+ (((x) & 0x0000ff0000000000ull) >> 24) | \
+ (((x) & 0x000000ff00000000ull) >> 8) | \
+ (((x) & 0x00000000ff000000ull) << 8) | \
+ (((x) & 0x0000000000ff0000ull) << 24) | \
+ (((x) & 0x000000000000ff00ull) << 40) | \
+ (((x) & 0x00000000000000ffull) << 56)))
+#endif
+
+#ifndef htonll
+#define htonll ntohll
+#endif
+
+#ifndef ntohl
+#define ntohl(x) ((uint32_t) \
+ ((((x) & 0xff000000) >> 24) | \
+ (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | \
+ (((x) & 0x000000ff) << 24)))
+#endif
+
+#ifndef htonl
+#define htonl ntohl
+#endif
+
+#ifndef htons
+#define htons(x) ((uint16_t) \
+ ((((x) & 0xff00) >> 8) | \
+ (((x) & 0x00ff) << 8)))
+#endif
+
+#ifndef ntohs
+#define ntohs htons
+#endif
+
+#endif
+#endif
diff --git a/libs/os/include/os/os_mbuf.h b/libs/os/include/os/os_mbuf.h
index 881ddba..9eaee38 100644
--- a/libs/os/include/os/os_mbuf.h
+++ b/libs/os/include/os/os_mbuf.h
@@ -17,6 +17,7 @@
#ifndef _OS_MBUF_H
#define _OS_MBUF_H
+#include "os/queue.h"
#include "os/os_eventq.h"
/**
@@ -40,6 +41,11 @@
* The memory pool which to allocate mbufs out of
*/
struct os_mempool *omp_pool;
+
+ /**
+ * Link to the next mbuf pool for system memory pools.
+ */
+ STAILQ_ENTRY(os_mbuf_pool) omp_next;
};
@@ -126,6 +132,12 @@
#define OS_MBUF_PKTHDR_TO_MBUF(__hdr) \
(struct os_mbuf *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf))
+/**
+ * Gets the length of an entire mbuf chain. The specified mbuf must have a
+ * packet header.
+ */
+#define OS_MBUF_PKTLEN(__om) (OS_MBUF_PKTHDR(__om)->omp_len)
+
/*
* Access the data of a mbuf, and cast it to type
*
@@ -201,6 +213,16 @@
/* Put an element in a mbuf queue */
int os_mqueue_put(struct os_mqueue *, struct os_eventq *, struct os_mbuf *);
+/* Register an mbuf pool with the system pool registry */
+int os_msys_register(struct os_mbuf_pool *);
+
+/* Return a mbuf from the system pool, given an indicative mbuf size */
+struct os_mbuf *os_msys_get(uint16_t dsize, uint16_t leadingspace);
+
+/* Return a packet header mbuf from the system pool */
+struct os_mbuf *os_msys_get_pkthdr(uint16_t dsize, uint16_t pkthdr_len);
+
+
/* Initialize a mbuf pool */
int os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
uint16_t, uint16_t);
@@ -237,5 +259,6 @@
int os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
void os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
void *os_mbuf_extend(struct os_mbuf *om, uint16_t len);
+struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
#endif /* _OS_MBUF_H */
diff --git a/libs/os/include/os/os_mutex.h b/libs/os/include/os/os_mutex.h
index 716ba60..a16c370 100644
--- a/libs/os/include/os/os_mutex.h
+++ b/libs/os/include/os/os_mutex.h
@@ -22,11 +22,11 @@
struct os_mutex
{
+ SLIST_HEAD(, os_task) mu_head; /* chain of waiting tasks */
uint8_t _pad;
uint8_t mu_prio; /* owner's default priority*/
uint16_t mu_level; /* call nesting level */
struct os_task *mu_owner; /* owners task */
- SLIST_HEAD(, os_task) mu_head; /* chain of waiting tasks */
};
/*
diff --git a/libs/os/include/os/os_sem.h b/libs/os/include/os/os_sem.h
index 73e84ee..b0eb8bf 100644
--- a/libs/os/include/os/os_sem.h
+++ b/libs/os/include/os/os_sem.h
@@ -21,9 +21,9 @@
struct os_sem
{
+ SLIST_HEAD(, os_task) sem_head; /* chain of waiting tasks */
uint16_t _pad;
uint16_t sem_tokens; /* # of tokens */
- SLIST_HEAD(, os_task) sem_head; /* chain of waiting tasks */
};
/*
diff --git a/libs/os/include/os/os_task.h b/libs/os/include/os/os_task.h
index 3f75432..ae44a73 100644
--- a/libs/os/include/os/os_task.h
+++ b/libs/os/include/os/os_task.h
@@ -29,6 +29,18 @@
#define OS_TASK_NAME_SIZE (36)
#endif
+/*
+ * Generic "object" structure. All objects that a task can wait on must
+ * have a SLIST_HEAD(, os_task) head_name as the first element in the object
+ * structure. The element 'head_name' can be any name. See os_mutex.h or
+ * os_sem.h for an example.
+ */
+struct os_task_obj
+{
+ SLIST_HEAD(, os_task) obj_head; /* chain of waiting tasks */
+};
+
+/* Task states */
typedef enum os_task_state {
OS_TASK_READY = 1,
OS_TASK_SLEEP = 2
@@ -37,6 +49,7 @@
/* Task flags */
#define OS_TASK_FLAG_NO_TIMEOUT (0x0001U)
#define OS_TASK_FLAG_SEM_WAIT (0x0002U)
+#define OS_TASK_FLAG_MUTEX_WAIT (0x0004U)
typedef void (*os_task_func_t)(void *);
@@ -54,7 +67,7 @@
os_task_func_t t_func;
void *t_arg;
- struct os_mutex *t_mutex;
+ void *t_obj;
struct os_sanity_check t_sanity_check;
diff --git a/libs/os/include/os/queue.h b/libs/os/include/os/queue.h
index 39826dd..4f5cacf 100755
--- a/libs/os/include/os/queue.h
+++ b/libs/os/include/os/queue.h
@@ -242,7 +242,7 @@
(STAILQ_EMPTY(head) ? \
NULL : \
((struct type *) \
- ((char *)((head)->stqh_last) - __offsetof(struct type, field))))
+ ((char *)((head)->stqh_last) - offsetof(struct type, field))))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
diff --git a/libs/os/src/arch/sim/os_fault.c b/libs/os/src/arch/sim/os_fault.c
index 8bd8fbe..f6aa6cb 100644
--- a/libs/os/src/arch/sim/os_fault.c
+++ b/libs/os/src/arch/sim/os_fault.c
@@ -27,4 +27,5 @@
snprintf(msg, sizeof(msg), "assert at %s:%d\n", file, line);
write(1, msg, strlen(msg));
+ _exit(1);
}
diff --git a/libs/os/src/os_eventq.c b/libs/os/src/os_eventq.c
index 3515a22..ca729db 100644
--- a/libs/os/src/os_eventq.c
+++ b/libs/os/src/os_eventq.c
@@ -48,6 +48,7 @@
resched = 0;
if (evq->evq_task) {
os_sched_wakeup(evq->evq_task);
+ evq->evq_task = NULL;
resched = 1;
}
diff --git a/libs/os/src/os_info.c b/libs/os/src/os_info.c
index ebb6f12..2387cdd 100644
--- a/libs/os/src/os_info.c
+++ b/libs/os/src/os_info.c
@@ -69,7 +69,7 @@
name = NULL;
found = 0;
- if (argv[1] != NULL && strcmp(argv[1], "")) {
+ if (argc > 1 && strcmp(argv[1], "")) {
name = argv[1];
}
@@ -95,7 +95,7 @@
}
console_printf(" %s (prio: %u, nw: %u, flags: 0x%x, "
- "ssize: %u, cswcnt: %lu, tot_run_time: %ums)",
+ "ssize: %u, cswcnt: %lu, tot_run_time: %ums)\n",
info[i].oti_name,
info[i].oti_prio, info[i].oti_next_wakeup, info[i].oti_flags,
info[i].oti_stack_size,
diff --git a/libs/os/src/os_mbuf.c b/libs/os/src/os_mbuf.c
index b1be0fc..f14466a 100644
--- a/libs/os/src/os_mbuf.c
+++ b/libs/os/src/os_mbuf.c
@@ -54,6 +54,9 @@
#include <string.h>
+STAILQ_HEAD(, os_mbuf_pool) g_msys_pool_list =
+ STAILQ_HEAD_INITIALIZER(g_msys_pool_list);
+
int
os_mqueue_init(struct os_mqueue *mq, void *arg)
{
@@ -84,7 +87,11 @@
}
OS_EXIT_CRITICAL(sr);
- m = OS_MBUF_PKTHDR_TO_MBUF(mp);
+ if (mp) {
+ m = OS_MBUF_PKTHDR_TO_MBUF(mp);
+ } else {
+ m = NULL;
+ }
return (m);
}
@@ -117,6 +124,83 @@
return (rc);
}
+int
+os_msys_register(struct os_mbuf_pool *new_pool)
+{
+ struct os_mbuf_pool *pool;
+
+ pool = NULL;
+ STAILQ_FOREACH(pool, &g_msys_pool_list, omp_next) {
+ if (new_pool->omp_databuf_len > pool->omp_databuf_len) {
+ break;
+ }
+ }
+
+ if (pool) {
+ STAILQ_INSERT_AFTER(&g_msys_pool_list, pool, new_pool, omp_next);
+ } else {
+ STAILQ_INSERT_TAIL(&g_msys_pool_list, new_pool, omp_next);
+ }
+
+ return (0);
+}
+
+static struct os_mbuf_pool *
+_os_msys_find_pool(uint16_t dsize)
+{
+ struct os_mbuf_pool *pool;
+
+ pool = NULL;
+ STAILQ_FOREACH(pool, &g_msys_pool_list, omp_next) {
+ if (dsize <= pool->omp_databuf_len) {
+ break;
+ }
+ }
+
+ if (!pool) {
+ pool = STAILQ_LAST(&g_msys_pool_list, os_mbuf_pool, omp_next);
+ }
+
+ return (pool);
+}
+
+
+
+struct os_mbuf *
+os_msys_get(uint16_t dsize, uint16_t leadingspace)
+{
+ struct os_mbuf *m;
+ struct os_mbuf_pool *pool;
+
+ pool = _os_msys_find_pool(dsize);
+ if (!pool) {
+ goto err;
+ }
+
+ m = os_mbuf_get(pool, leadingspace);
+ return (m);
+err:
+ return (NULL);
+}
+
+
+struct os_mbuf *
+os_msys_get_pkthdr(uint16_t dsize, uint16_t pkthdr_len)
+{
+ struct os_mbuf *m;
+ struct os_mbuf_pool *pool;
+
+ pool = _os_msys_find_pool(dsize + pkthdr_len);
+ if (!pool) {
+ goto err;
+ }
+
+ m = os_mbuf_get_pkthdr(pool, pkthdr_len);
+ return (m);
+err:
+ return (NULL);
+}
+
/**
* Initialize a pool of mbufs.
@@ -161,6 +245,7 @@
SLIST_NEXT(om, om_next) = NULL;
om->om_flags = 0;
+ om->om_pkthdr_len = 0;
om->om_len = 0;
om->om_data = (&om->om_databuf[0] + leadingspace);
om->om_omp = omp;
@@ -204,9 +289,11 @@
{
int rc;
- rc = os_memblock_put(om->om_omp->omp_pool, om);
- if (rc != 0) {
- goto err;
+ if (om->om_omp != NULL) {
+ rc = os_memblock_put(om->om_omp->omp_pool, om);
+ if (rc != 0) {
+ goto err;
+ }
}
return (0);
@@ -829,8 +916,6 @@
return data;
}
-#if 0
-
/**
* Rearrange a mbuf chain so that len bytes are contiguous,
* and in the data area of an mbuf (so that OS_MBUF_DATA() will
@@ -851,40 +936,58 @@
os_mbuf_pullup(struct os_mbuf *om, uint16_t len)
{
struct os_mbuf_pool *omp;
- struct os_mbuf *newm;
+ struct os_mbuf *next;
+ struct os_mbuf *om2;
+ int count;
+ int space;
omp = om->om_omp;
- if (len > omp->omp_databuf_len) {
- goto err;
- }
-
- /* Is 'n' bytes already contiguous? */
- if (((uint8_t *) &om->om_databuf[0] + omp->omp_databuf_len) -
- OS_MBUF_DATA(om, uint8_t *) >= len) {
- newm = om;
- goto done;
- }
-
- /* Nope, OK. Allocate a new buffer, and then go through and copy 'n'
- * bytes into that buffer.
+ /*
+ * If first mbuf has no cluster, and has room for len bytes
+ * without shifting current data, pullup into it,
+ * otherwise allocate a new mbuf to prepend to the chain.
*/
- newm = os_mbuf_get(omp, 0);
- if (!newm) {
- goto err;
+ if (om->om_len >= len) {
+ return (om);
}
-
- written = 0;
- while (written < len
-
-
-done:
- return (newm);
-err:
- if (om) {
- os_mbuf_free_chain(om);
+ if (om->om_len + OS_MBUF_TRAILINGSPACE(om) >= len &&
+ SLIST_NEXT(om, om_next)) {
+ om2 = om;
+ om = SLIST_NEXT(om, om_next);
+ len -= om2->om_len;
+ } else {
+ if (len > omp->omp_databuf_len - om->om_pkthdr_len)
+ goto bad;
+ om2 = os_mbuf_get(omp, 0);
+ if (om2 == NULL)
+ goto bad;
+ if (OS_MBUF_IS_PKTHDR(om))
+ _os_mbuf_copypkthdr(om2, om);
}
-
+ space = OS_MBUF_TRAILINGSPACE(om2);
+ do {
+ count = min(min(len, space), om->om_len);
+ memcpy(om2->om_data + om2->om_len, om->om_data, count);
+ len -= count;
+ om2->om_len += count;
+ om->om_len -= count;
+ space -= count;
+ if (om->om_len)
+ om->om_data += count;
+ else {
+ next = SLIST_NEXT(om, om_next);
+ os_mbuf_free(om);
+ om = next;
+ }
+ } while (len > 0 && om);
+ if (len > 0) {
+ os_mbuf_free(om2);
+ goto bad;
+ }
+ SLIST_NEXT(om2, om_next) = om;
+ return (om2);
+bad:
+ os_mbuf_free_chain(om);
return (NULL);
}
-#endif
diff --git a/libs/os/src/os_mutex.c b/libs/os/src/os_mutex.c
index 3ad3151..0965be8 100644
--- a/libs/os/src/os_mutex.c
+++ b/libs/os/src/os_mutex.c
@@ -98,11 +98,7 @@
rdy = SLIST_FIRST(&mu->mu_head);
if (rdy) {
/* There is one waiting. Wake it up */
- assert(rdy->t_mutex);
- rdy->t_mutex = NULL;
-
- SLIST_REMOVE_HEAD(&mu->mu_head, t_obj_list);
- SLIST_NEXT(rdy, t_obj_list) = NULL;
+ assert(rdy->t_obj);
os_sched_wakeup(rdy);
/* Set mutex internals */
@@ -214,13 +210,17 @@
}
/* Set mutex pointer in task */
- current->t_mutex = mu;
+ current->t_obj = mu;
+ current->t_flags |= OS_TASK_FLAG_MUTEX_WAIT;
os_sched_sleep(current, timeout);
-
OS_EXIT_CRITICAL(sr);
os_sched(NULL, 0);
+ OS_ENTER_CRITICAL(sr);
+ current->t_flags &= ~OS_TASK_FLAG_MUTEX_WAIT;
+ OS_EXIT_CRITICAL(sr);
+
/* If we are owner we did not time out. */
if (mu->mu_owner == current) {
rc = OS_OK;
@@ -276,10 +276,7 @@
/* Now, go through all the tasks waiting on the mutex */
while (!SLIST_EMPTY(&mu->mu_head)) {
rdy = SLIST_FIRST(&mu->mu_head);
- assert(rdy->t_mutex);
- rdy->t_mutex = NULL;
- SLIST_REMOVE_HEAD(&mu->mu_head, t_obj_list);
- SLIST_NEXT(rdy, t_obj_list) = NULL;
+ assert(rdy->t_obj);
os_sched_wakeup(rdy);
}
diff --git a/libs/os/src/os_sched.c b/libs/os/src/os_sched.c
index 944f0f6..f1c03c6 100644
--- a/libs/os/src/os_sched.c
+++ b/libs/os/src/os_sched.c
@@ -243,12 +243,17 @@
int
os_sched_wakeup(struct os_task *t)
{
- /* Remove self from mutex list if waiting on one */
- if (t->t_mutex) {
- assert(!SLIST_EMPTY(&t->t_mutex->mu_head));
- SLIST_REMOVE(&t->t_mutex->mu_head, t, os_task, t_obj_list);
+ struct os_task_obj *os_obj;
+
+ assert(t->t_state == OS_TASK_SLEEP);
+
+ /* Remove self from object list if waiting on one */
+ if (t->t_obj) {
+ os_obj = (struct os_task_obj *)t->t_obj;
+ assert(!SLIST_EMPTY(&os_obj->obj_head));
+ SLIST_REMOVE(&os_obj->obj_head, t, os_task, t_obj_list);
SLIST_NEXT(t, t_obj_list) = NULL;
- t->t_mutex = NULL;
+ t->t_obj = NULL;
}
/* Remove task from sleep list */
diff --git a/libs/os/src/os_sem.c b/libs/os/src/os_sem.c
index d3b395c..84464d3 100644
--- a/libs/os/src/os_sem.c
+++ b/libs/os/src/os_sem.c
@@ -86,12 +86,8 @@
/* Check if tasks are waiting for the semaphore */
rdy = SLIST_FIRST(&sem->sem_head);
if (rdy) {
- /* Clear flag that we are waiting on the semaphore */
+ /* Clear flag that we are waiting on the semaphore; wake up task */
rdy->t_flags &= ~OS_TASK_FLAG_SEM_WAIT;
-
- /* There is one waiting. Wake it up */
- SLIST_REMOVE_HEAD(&sem->sem_head, t_obj_list);
- SLIST_NEXT(rdy, t_obj_list) = NULL;
os_sched_wakeup(rdy);
/* Schedule if waiting task higher priority */
@@ -169,6 +165,7 @@
rc = OS_OK;
/* Link current task to tasks waiting for semaphore */
+ current->t_obj = sem;
current->t_flags |= OS_TASK_FLAG_SEM_WAIT;
last = NULL;
if (!SLIST_EMPTY(&sem->sem_head)) {
@@ -258,9 +255,7 @@
/* Now, go through all the tasks waiting on the semaphore */
while (rdy != NULL) {
- SLIST_REMOVE_HEAD(&sem->sem_head, t_obj_list);
- SLIST_NEXT(rdy, t_obj_list) = NULL;
- os_sched_wakeup(rdy);
+ os_sched_wakeup(rdy);
rdy = SLIST_FIRST(&sem->sem_head);
}
}
diff --git a/libs/os/src/test/mbuf_test.c b/libs/os/src/test/mbuf_test.c
index 8652494..fb7c4de 100644
--- a/libs/os/src/test/mbuf_test.c
+++ b/libs/os/src/test/mbuf_test.c
@@ -50,6 +50,8 @@
struct os_mbuf *m;
int rc;
+ os_mbuf_test_setup();
+
m = os_mbuf_get(&os_mbuf_pool, 0);
TEST_ASSERT_FATAL(m != NULL, "Error allocating mbuf");
@@ -64,6 +66,8 @@
struct os_mbuf *dup;
int rc;
+ os_mbuf_test_setup();
+
/* Test first allocating and duplicating a single mbuf */
m = os_mbuf_get(&os_mbuf_pool, 0);
TEST_ASSERT_FATAL(m != NULL, "Error allocating mbuf");
@@ -106,6 +110,8 @@
uint8_t databuf[] = {0xa, 0xb, 0xc, 0xd};
uint8_t cmpbuf[] = {0xff, 0xff, 0xff, 0xff};
+ os_mbuf_test_setup();
+
m = os_mbuf_get(&os_mbuf_pool, 0);
TEST_ASSERT_FATAL(m != NULL, "Error allocating mbuf");
@@ -121,15 +127,98 @@
"Databuf doesn't match cmpbuf");
}
-TEST_SUITE(os_mbuf_test_case_4)
+static void
+os_mbuf_test_misc_assert_contiguous(struct os_mbuf *om, void *data, int len)
{
+ TEST_ASSERT_FATAL(om != NULL);
+
+ if (OS_MBUF_IS_PKTHDR(om)) {
+ TEST_ASSERT(OS_MBUF_PKTLEN(om) == len);
+ }
+ TEST_ASSERT(om->om_len == len);
+ TEST_ASSERT(memcmp(om->om_data, data, len) == 0);
+}
+
+TEST_CASE(os_mbuf_test_pullup)
+{
+ struct os_mbuf *om;
+ struct os_mbuf *om2;
+ uint8_t data[256];
+ int rc;
+ int i;
+
+ os_mbuf_test_setup();
+
+ for (i = 0; i < sizeof data; i++) {
+ data[i] = i;
+ }
+
+ /*** Free when too much data is requested. */
+ om = os_mbuf_get_pkthdr(&os_mbuf_pool, 0);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ om = os_mbuf_pullup(om, 1);
+ TEST_ASSERT(om == NULL);
+
+ /*** No effect when all data is already at the start. */
+ om = os_mbuf_get_pkthdr(&os_mbuf_pool, 0);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ rc = os_mbuf_append(om, data, 1);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_mbuf_test_misc_assert_contiguous(om, data, 1);
+
+ om = os_mbuf_pullup(om, 1);
+ os_mbuf_test_misc_assert_contiguous(om, data, 1);
+
+ /*** Spread data across four mbufs. */
+ om2 = os_mbuf_get(&os_mbuf_pool, 0);
+ TEST_ASSERT_FATAL(om2 != NULL);
+ rc = os_mbuf_append(om2, data + 1, 1);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_mbuf_concat(om, om2);
+
+ om2 = os_mbuf_get(&os_mbuf_pool, 0);
+ TEST_ASSERT_FATAL(om2 != NULL);
+ rc = os_mbuf_append(om2, data + 2, 1);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_mbuf_concat(om, om2);
+
+ om2 = os_mbuf_get(&os_mbuf_pool, 0);
+ TEST_ASSERT_FATAL(om2 != NULL);
+ rc = os_mbuf_append(om2, data + 3, 1);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_mbuf_concat(om, om2);
+
+ TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(om) == 4);
+
+ om = os_mbuf_pullup(om, 4);
+ os_mbuf_test_misc_assert_contiguous(om, data, 4);
+
+ os_mbuf_free_chain(om);
+
+ /*** Require an allocation. */
+ om = os_mbuf_get_pkthdr(&os_mbuf_pool, 0);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ om->om_data += 100;
+ rc = os_mbuf_append(om, data, 100);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ om2 = os_mbuf_get(&os_mbuf_pool, 0);
+ TEST_ASSERT_FATAL(om2 != NULL);
+ rc = os_mbuf_append(om2, data + 100, 100);
+ TEST_ASSERT_FATAL(rc == 0);
+ os_mbuf_concat(om, om2);
+
+ om = os_mbuf_pullup(om, 200);
+ os_mbuf_test_misc_assert_contiguous(om, data, 200);
}
TEST_SUITE(os_mbuf_test_suite)
{
- os_mbuf_test_setup();
-
os_mbuf_test_case_1();
os_mbuf_test_case_2();
os_mbuf_test_case_3();
+ os_mbuf_test_pullup();
}
diff --git a/libs/os/src/test/mutex_test.c b/libs/os/src/test/mutex_test.c
index a861dbb..7d9a08c 100644
--- a/libs/os/src/test/mutex_test.c
+++ b/libs/os/src/test/mutex_test.c
@@ -178,6 +178,14 @@
g_task14_val = 1;
os_time_delay(100);
+ /*
+ * Task17 should have its mutex wait flag set; at least the first time
+ * through!
+ */
+ if (iters == 0) {
+ TEST_ASSERT(task17.t_flags & OS_TASK_FLAG_MUTEX_WAIT);
+ }
+
if (g_mutex_test == 4) {
os_mutex_delete(&g_mutex1);
os_time_delay(150);
@@ -303,6 +311,7 @@
err = os_mutex_pend(&g_mutex1, 10);
} else {
err = os_mutex_pend(&g_mutex1, 10000);
+ TEST_ASSERT((t->t_flags & OS_TASK_FLAG_MUTEX_WAIT) == 0);
}
if (g_mutex_test == 4 || g_mutex_test == 5) {
diff --git a/libs/os/src/test/sem_test.c b/libs/os/src/test/sem_test.c
index 75b2e40..fbaf82b 100644
--- a/libs/os/src/test/sem_test.c
+++ b/libs/os/src/test/sem_test.c
@@ -95,7 +95,7 @@
while (1) {
err = os_sem_pend(&g_sem1, timeout);
- TEST_ASSERT(err == OS_OK);
+ TEST_ASSERT((err == OS_OK) || (err == OS_TIMEOUT));
err = os_sem_release(&g_sem1);
TEST_ASSERT(err == OS_OK);
diff --git a/libs/util/include/util/base64.h b/libs/util/include/util/base64.h
new file mode 100644
index 0000000..fff40fd
--- /dev/null
+++ b/libs/util/include/util/base64.h
@@ -0,0 +1,26 @@
+/**
+ * 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_BASE64_H
+#define __UTIL_BASE64_H
+
+#include <stdint.h>
+
+int base64_encode(const void *, int, char *, uint8_t);
+int base64_decode(const char *, void *buf);
+
+#define BASE64_ENCODE_SIZE(__size) (((__size) * (4 / 3)) + 4)
+
+#endif /* __UTIL_BASE64_H__ */
diff --git a/libs/util/src/base64.c b/libs/util/src/base64.c
new file mode 100644
index 0000000..3b07362
--- /dev/null
+++ b/libs/util/src/base64.c
@@ -0,0 +1,167 @@
+/**
+ * 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.
+ */
+
+/*
+ * This file is based on roken from the FreeBSD source. It has been modified
+ * to not use malloc() and instead expect static buffers, and tabs have been
+ * replaced with spaces. Also, instead of strlen() on the resulting string,
+ * pointer arithmitic is done, as p represents the end of the buffer.
+ */
+
+/*
+ * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <util/base64.h>
+
+static const char base64_chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static int
+pos(char c)
+{
+ const char *p;
+ for (p = base64_chars; *p; p++)
+ if (*p == c)
+ return p - base64_chars;
+ return -1;
+}
+
+int
+base64_encode(const void *data, int size, char *s, uint8_t should_pad)
+{
+ char *p;
+ int i;
+ int c;
+ const unsigned char *q;
+ char *last;
+ int diff;
+
+ p = s;
+
+ q = (const unsigned char *) data;
+ last = NULL;
+ i = 0;
+ while (i < size) {
+ c = q[i++];
+ c *= 256;
+ if (i < size)
+ c += q[i];
+ i++;
+ c *= 256;
+ if (i < size)
+ c += q[i];
+ i++;
+ p[0] = base64_chars[(c & 0x00fc0000) >> 18];
+ p[1] = base64_chars[(c & 0x0003f000) >> 12];
+ p[2] = base64_chars[(c & 0x00000fc0) >> 6];
+ p[3] = base64_chars[(c & 0x0000003f) >> 0];
+ last = p;
+ p += 4;
+ }
+
+ if (last) {
+ diff = i - size;
+ if (diff > 0) {
+ if (should_pad) {
+ memset(last + (4 - diff), '=', diff);
+ } else {
+ p = last + (4 - diff);
+ }
+ }
+ }
+
+ *p = 0;
+
+ return (p - s);
+}
+
+#define DECODE_ERROR -1
+
+static unsigned int
+token_decode(const char *token)
+{
+ int i;
+ unsigned int val = 0;
+ int marker = 0;
+ if (strlen(token) < 4)
+ return DECODE_ERROR;
+ for (i = 0; i < 4; i++) {
+ val *= 64;
+ if (token[i] == '=')
+ marker++;
+ else if (marker > 0)
+ return DECODE_ERROR;
+ else
+ val += pos(token[i]);
+ }
+ if (marker > 2)
+ return DECODE_ERROR;
+ return (marker << 24) | val;
+}
+
+int
+base64_decode(const char *str, void *data)
+{
+ const char *p;
+ unsigned char *q;
+
+ q = data;
+ for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) {
+ unsigned int val = token_decode(p);
+ unsigned int marker = (val >> 24) & 0xff;
+ if (val == DECODE_ERROR)
+ return -1;
+ *q++ = (val >> 16) & 0xff;
+ if (marker < 2)
+ *q++ = (val >> 8) & 0xff;
+ if (marker < 1)
+ *q++ = val & 0xff;
+ }
+ return q - (unsigned char *) data;
+}
diff --git a/libs/util/src/flash_map.c b/libs/util/src/flash_map.c
index 28f26c9..81d0f22 100644
--- a/libs/util/src/flash_map.c
+++ b/libs/util/src/flash_map.c
@@ -82,36 +82,69 @@
}
#ifdef NFFS_PRESENT
+/*
+ * Turn flash region into a set of areas for NFFS use.
+ *
+ * Limit the number of regions we return to be less than *cnt.
+ * If sector count within region exceeds that, collect multiple sectors
+ * to a region.
+ */
int
flash_area_to_nffs_desc(int idx, int *cnt, struct nffs_area_desc *nad)
{
- int i;
+ int i, j;
const struct hal_flash *hf;
const struct flash_area *fa;
+ int max_cnt, move_on;
+ int first_idx, last_idx;
uint32_t start, size;
+ uint32_t min_size;
if (!flash_map || idx >= flash_map_entries) {
return -1;
}
+ first_idx = last_idx = -1;
+ max_cnt = *cnt;
*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++;
+ if (first_idx == -1) {
+ first_idx = i;
}
+ last_idx = i;
*cnt = *cnt + 1;
}
}
- if (nad) {
- memset(nad, 0, sizeof(*nad));
+ if (*cnt > max_cnt) {
+ min_size = fa->fa_size / max_cnt;
+ } else {
+ min_size = 0;
}
+ *cnt = 0;
+
+ move_on = 1;
+ for (i = first_idx, j = 0; i < last_idx + 1; i++) {
+ hf->hf_itf->hff_sector_info(i, &start, &size);
+ if (move_on) {
+ nad[j].nad_flash_id = fa->fa_flash_id;
+ nad[j].nad_offset = start;
+ nad[j].nad_length = size;
+ *cnt = *cnt + 1;
+ move_on = 0;
+ } else {
+ nad[j].nad_length += size;
+ }
+ if (nad[j].nad_length >= min_size) {
+ j++;
+ move_on = 1;
+ }
+ }
+ nad[*cnt].nad_length = 0;
return 0;
}
#endif /* NFFS_PRESENT */
diff --git a/libs/util/src/stats.c b/libs/util/src/stats.c
index 0d2eb36..e61d785 100644
--- a/libs/util/src/stats.c
+++ b/libs/util/src/stats.c
@@ -43,6 +43,7 @@
struct shell_cmd shell_stats_cmd;
#endif
+
#ifdef SHELL_PRESENT
static void
@@ -130,6 +131,7 @@
#endif
+
int
stats_module_init(void)
{
@@ -141,6 +143,7 @@
}
#endif
+
rc = stats_init(STATS_HDR(stats), STATS_SIZE_INIT_PARMS(stats, STATS_SIZE_32),
STATS_NAME_INIT_PARMS(stats));
if (rc != 0) {