You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/07/08 21:20:04 UTC

[17/50] [abbrv] incubator-mynewt-core git commit: MYNEWT-79: fix native cputime and add the common hal source file

MYNEWT-79: fix native cputime and add the common hal source file


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/712374ac
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/712374ac
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/712374ac

Branch: refs/heads/master
Commit: 712374ac2ae9a5b8465eab0cb6242f93165cc00a
Parents: 183873d
Author: William San Filippo <wi...@runtime.io>
Authored: Thu Jun 23 16:14:56 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Thu Jun 23 16:39:04 2016 -0700

----------------------------------------------------------------------
 hw/hal/src/hal_cputime.c        | 342 +++++++++++++++++++++++++++++++++++
 hw/mcu/native/src/hal_cputime.c |   6 +
 2 files changed, 348 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/712374ac/hw/hal/src/hal_cputime.c
----------------------------------------------------------------------
diff --git a/hw/hal/src/hal_cputime.c b/hw/hal/src/hal_cputime.c
new file mode 100644
index 0000000..980b3e1
--- /dev/null
+++ b/hw/hal/src/hal_cputime.c
@@ -0,0 +1,342 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <assert.h>
+#include "os/os.h"
+#include "hal/hal_cputime.h"
+
+/* XXX:
+ *  - Must determine how to set priority of cpu timer interrupt
+ *  - Determine if we should use a mutex as opposed to disabling interrupts
+ *  - Should I use macro for compare channel?
+ *  - Sync to OSTIME.
+ */
+struct cputime_data g_cputime;
+
+/* Queue for timers */
+TAILQ_HEAD(cputime_qhead, cpu_timer) g_cputimer_q;
+
+/**
+ * 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.
+ *
+ */
+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->link.tqe_prev = NULL;
+            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 {
+        cputime_disable_ocmp();
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+
+/**
+ * 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)
+{
+    int rc;
+
+    TAILQ_INIT(&g_cputimer_q);
+    rc = cputime_hw_init(clock_freq);
+    return rc;
+}
+
+
+/**
+ * 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).
+ * Cannot be called when the timer has already started.
+ *
+ * @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);
+    assert(timer->link.tqe_prev == 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 not 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 (timer->link.tqe_prev != NULL) {
+        reset_ocmp = 0;
+        if (timer == TAILQ_FIRST(&g_cputimer_q)) {
+            /* If first on queue, we will need to reset OCMP */
+            entry = TAILQ_NEXT(timer, link);
+            reset_ocmp = 1;
+        }
+        TAILQ_REMOVE(&g_cputimer_q, timer, link);
+        timer->link.tqe_prev = NULL;
+        if (reset_ocmp) {
+            if (entry) {
+                cputime_set_ocmp(entry);
+            } else {
+                cputime_disable_ocmp();
+            }
+        }
+    }
+
+    OS_EXIT_CRITICAL(sr);
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/712374ac/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
index 850bfc5..e310415 100644
--- a/hw/mcu/native/src/hal_cputime.c
+++ b/hw/mcu/native/src/hal_cputime.c
@@ -32,6 +32,12 @@ static uint32_t g_native_cputime_cputicks_per_ostick;
 static uint64_t g_native_cputime;
 static uint32_t g_native_cputime_last_ostime;
 
+void
+cputime_disable_ocmp(void)
+{
+    os_callout_stop(&g_native_cputimer.cf_c);
+}
+
 /**
  * Convert cpu time ticks to os ticks.
  *