You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by we...@apache.org on 2016/10/06 03:47:17 UTC

[1/2] incubator-mynewt-core git commit: MYNEWT-401: HAL Timer

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop ab85825ec -> 3cb38e68a


MYNEWT-401: HAL Timer

Add HAL timer for nrf51. Allow for 16-bit timers to be used as
32-bit timers without chaining timers. Add configurable
priority for each timer interrupt.


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/3cb38e68
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/3cb38e68
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/3cb38e68

Branch: refs/heads/develop
Commit: 3cb38e68a8ea34ad558d257aa0e6b86eebb6aa53
Parents: ba4aa33
Author: William San Filippo <wi...@runtime.io>
Authored: Wed Oct 5 20:45:50 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Wed Oct 5 20:47:10 2016 -0700

----------------------------------------------------------------------
 apps/timtest/src/main.c                |  29 +-
 apps/timtest/syscfg.yml                |   1 +
 hw/bsp/nrf51dk/syscfg.yml              |   9 +
 hw/bsp/nrf52dk/syscfg.yml              |  15 +
 hw/mcu/nordic/nrf51xxx/src/hal_timer.c | 746 ++++++++++++++++++++++++++++
 hw/mcu/nordic/nrf52xxx/src/hal_timer.c |  19 +
 6 files changed, 807 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3cb38e68/apps/timtest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/timtest/src/main.c b/apps/timtest/src/main.c
index e51822a..aa0cb8a 100755
--- a/apps/timtest/src/main.c
+++ b/apps/timtest/src/main.c
@@ -40,7 +40,7 @@ struct os_task task1;
 os_stack_t stack1[TASK1_STACK_SIZE];
 
 #define TASK1_TIMER_NUM     (1)
-#define TASK1_TIMER_FREQ    (1000000)
+#define TASK1_TIMER_FREQ    (4000000)
 
 /* Task 2 */
 #define TASK2_PRIO (2)
@@ -49,7 +49,7 @@ struct os_task task2;
 os_stack_t stack2[TASK2_STACK_SIZE];
 
 #define TASK2_TIMER_NUM     (2)
-#define TASK2_TIMER_FREQ    (250000)
+#define TASK2_TIMER_FREQ    (62500)
 
 /* For LED toggling */
 int g_led1_pin;
@@ -58,6 +58,7 @@ struct os_sem g_test_sem;
 
 struct hal_timer g_task1_timer;
 uint32_t task1_timer_arg = 0xdeadc0de;
+uint32_t g_task1_loops;
 
 void
 task1_timer_cb(void *arg)
@@ -74,7 +75,6 @@ void
 task1_handler(void *arg)
 {
     int rc;
-    int cntr;
     uint32_t timer_cntr;
 
     /* Task 1 toggles LED 1 (LED_BLINK_PIN) */
@@ -84,7 +84,7 @@ task1_handler(void *arg)
     hal_timer_set_cb(TASK1_TIMER_NUM, &g_task1_timer, task1_timer_cb,
                      &task1_timer_arg);
 
-    cntr = 0;
+    g_task1_loops = 0;
     rc = hal_timer_start(&g_task1_timer, TASK1_TIMER_FREQ);
     assert(rc == 0);
 
@@ -95,17 +95,17 @@ task1_handler(void *arg)
         /* Toggle the LED */
         hal_gpio_toggle(g_led1_pin);
 
-        ++cntr;
-        if (cntr & 1) {
+        ++g_task1_loops;
+        if (g_task1_loops & 1) {
             timer_cntr = hal_timer_read(TASK1_TIMER_NUM);
             hal_timer_start_at(&g_task1_timer, timer_cntr + TASK1_TIMER_FREQ);
-            if ((cntr % 10) == 0) {
+            if ((g_task1_loops % 10) == 0) {
                 hal_timer_stop(&g_task1_timer);
                 os_sem_release(&g_test_sem);
             }
         } else {
             hal_timer_start(&g_task1_timer, TASK1_TIMER_FREQ);
-            if ((cntr % 10) == 0) {
+            if ((g_task1_loops % 10) == 0) {
                 hal_timer_stop(&g_task1_timer);
                 os_sem_release(&g_test_sem);
             }
@@ -147,20 +147,25 @@ task2_handler(void *arg)
 int
 init_tasks(void)
 {
+    int rc;
     uint32_t res;
 
     /* Initialize global test semaphore */
     os_sem_init(&g_test_sem, 0);
 
     /* Initialize timer 0 to count at 1 MHz */
-    hal_timer_init(TASK1_TIMER_NUM, TASK1_TIMER_FREQ);
+    rc = hal_timer_init(TASK1_TIMER_NUM, TASK1_TIMER_FREQ);
+    assert(rc == 0);
+
     res = hal_timer_get_resolution(TASK1_TIMER_NUM);
-    assert(res == 1000);
+    assert(res == (1000000000 / TASK1_TIMER_FREQ));
 
     /* Initialize timer 1 to count at 250 kHz */
-    hal_timer_init(TASK2_TIMER_NUM, TASK2_TIMER_FREQ);
+    rc = hal_timer_init(TASK2_TIMER_NUM, TASK2_TIMER_FREQ);
+    assert(rc == 0);
+
     res = hal_timer_get_resolution(TASK2_TIMER_NUM);
-    assert(res == 4000);
+    assert(res == (1000000000 / TASK2_TIMER_FREQ));
 
     os_task_init(&task1, "task1", task1_handler, NULL,
             TASK1_PRIO, OS_WAIT_FOREVER, stack1, TASK1_STACK_SIZE);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3cb38e68/apps/timtest/syscfg.yml
----------------------------------------------------------------------
diff --git a/apps/timtest/syscfg.yml b/apps/timtest/syscfg.yml
index 619b4ec..3f2f1e8 100644
--- a/apps/timtest/syscfg.yml
+++ b/apps/timtest/syscfg.yml
@@ -2,5 +2,6 @@
 
 syscfg.vals:
     SHELL_TASK: 0
+    TIMER_0: 0
     TIMER_1: 1
     TIMER_2: 1

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3cb38e68/hw/bsp/nrf51dk/syscfg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51dk/syscfg.yml b/hw/bsp/nrf51dk/syscfg.yml
index bb85183..a11aa61 100644
--- a/hw/bsp/nrf51dk/syscfg.yml
+++ b/hw/bsp/nrf51dk/syscfg.yml
@@ -46,9 +46,18 @@ syscfg.defs:
     TIMER_0:
         description: 'NRF51 Timer 0'
         value:  0
+    TIMER_0_INTERRUPT_PRIORITY:
+        description: 'TBD'
+        value: '((1 << __NVIC_PRIO_BITS) - 1)'
     TIMER_1:
         description: 'NRF51 Timer 1'
         value:  0
+    TIMER_1_INTERRUPT_PRIORITY:
+        description: 'TBD'
+        value: '((1 << __NVIC_PRIO_BITS) - 1)'
     TIMER_2:
         description: 'NRF51 Timer 2'
         value:  0
+    TIMER_2_INTERRUPT_PRIORITY:
+        description: 'TBD'
+        value: '((1 << __NVIC_PRIO_BITS) - 1)'

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3cb38e68/hw/bsp/nrf52dk/syscfg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf52dk/syscfg.yml b/hw/bsp/nrf52dk/syscfg.yml
index 741f74a..002ac12 100644
--- a/hw/bsp/nrf52dk/syscfg.yml
+++ b/hw/bsp/nrf52dk/syscfg.yml
@@ -55,15 +55,30 @@ syscfg.defs:
     TIMER_0:
         description: 'NRF52 Timer 0'
         value:  0
+    TIMER_0_INTERRUPT_PRIORITY:
+        description: 'TBD'
+        value: '((1 << __NVIC_PRIO_BITS) - 1)'
     TIMER_1:
         description: 'NRF52 Timer 1'
         value:  0
+    TIMER_1_INTERRUPT_PRIORITY:
+        description: 'TBD'
+        value: '((1 << __NVIC_PRIO_BITS) - 1)'
     TIMER_2:
         description: 'NRF52 Timer 2'
         value:  0
+    TIMER_2_INTERRUPT_PRIORITY:
+        description: 'TBD'
+        value: '((1 << __NVIC_PRIO_BITS) - 1)'
     TIMER_3:
         description: 'NRF52 Timer 3'
         value:  0
+    TIMER_3_INTERRUPT_PRIORITY:
+        description: 'TBD'
+        value: '((1 << __NVIC_PRIO_BITS) - 1)'
     TIMER_4:
         description: 'NRF52 Timer 4'
         value:  0
+    TIMER_4_INTERRUPT_PRIORITY:
+        description: 'TBD'
+        value: '((1 << __NVIC_PRIO_BITS) - 1)'

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3cb38e68/hw/mcu/nordic/nrf51xxx/src/hal_timer.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf51xxx/src/hal_timer.c b/hw/mcu/nordic/nrf51xxx/src/hal_timer.c
new file mode 100644
index 0000000..92e0009
--- /dev/null
+++ b/hw/mcu/nordic/nrf51xxx/src/hal_timer.c
@@ -0,0 +1,746 @@
+/**
+ * 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 <errno.h>
+#include "syscfg/syscfg.h"
+#include "bsp/cmsis_nvic.h"
+#include "hal/hal_timer.h"
+#include "nrf51.h"
+#include "nrf51_bitfields.h"
+#include "mcu/nrf51_hal.h"
+
+/* IRQ prototype */
+typedef void (*hal_timer_irq_handler_t)(void);
+
+/*
+ * We may need to use up to three output compares: one to read the counter,
+ * one to generate the timer interrupt, and one to count overflows for a
+ * 16-bit timer.
+ */
+#define NRF_TIMER_CC_OVERFLOW   (1)
+#define NRF_TIMER_CC_READ       (2)
+#define NRF_TIMER_CC_INT        (3)
+
+/* XXX: what about RTC timers? How are they instantiated? How do we
+   relate timer numbers to them? */
+#define NRF51_HAL_TIMER_MAX     (3)
+
+/* Maximum timer frequency */
+#define NRF51_MAX_TIMER_FREQ    (16000000)
+
+/**
+ * tmr_enabled: flag set if timer is enabled
+ * tmr_irq_num: The irq number of this timer.
+ * tmr_16bit: flag set if timer is set to 16-bit mode.
+ * tmr_pad: padding.
+ * tmr_cntr: Used for timers that are not 32 bits. Upper 16 bits contain
+ *           current timer counter value; lower 16 bit come from hw timer.
+ *  tmr_isrs: count of # of timer interrupts.
+ *  tmr_freq: frequency of timer, in Hz.
+ *  tmr_reg: Pointer to timer base address
+ *  hal_timer_q: queue of linked list of software timers.
+ */
+struct nrf51_hal_timer {
+    uint8_t tmr_enabled;
+    uint8_t tmr_irq_num;
+    uint8_t tmr_16bit;
+    uint8_t tmr_pad;
+    uint32_t tmr_cntr;
+    uint32_t timer_isrs;
+    uint32_t tmr_freq;
+    NRF_TIMER_Type *tmr_reg;
+    TAILQ_HEAD(hal_timer_qhead, hal_timer) hal_timer_q;
+};
+
+#if MYNEWT_VAL(TIMER_0)
+struct nrf51_hal_timer nrf51_hal_timer0;
+#endif
+#if MYNEWT_VAL(TIMER_1)
+struct nrf51_hal_timer nrf51_hal_timer1;
+#endif
+#if MYNEWT_VAL(TIMER_2)
+struct nrf51_hal_timer nrf51_hal_timer2;
+#endif
+
+struct nrf51_hal_timer *nrf51_hal_timers[NRF51_HAL_TIMER_MAX] = {
+#if MYNEWT_VAL(TIMER_0)
+    &nrf51_hal_timer0,
+#else
+    NULL,
+#endif
+#if MYNEWT_VAL(TIMER_1)
+    &nrf51_hal_timer1,
+#else
+    NULL,
+#endif
+#if MYNEWT_VAL(TIMER_2)
+    &nrf51_hal_timer2,
+#else
+    NULL,
+#endif
+};
+
+/* Resolve timer number into timer structure */
+#define NRF51_HAL_TIMER_RESOLVE(__n, __v)       \
+    if ((__n) >= NRF51_HAL_TIMER_MAX) {         \
+        rc = EINVAL;                            \
+        goto err;                               \
+    }                                           \
+    (__v) = nrf51_hal_timers[(__n)];            \
+    if ((__v) == NULL) {                        \
+        rc = EINVAL;                            \
+        goto err;                               \
+    }
+
+/* Interrupt mask for interrupt enable/clear */
+#define NRF_TIMER_INT_MASK(x)    ((1 << (uint32_t)(x)) << 16)
+
+static uint32_t
+nrf_read_timer_cntr(NRF_TIMER_Type *hwtimer)
+{
+    uint32_t tcntr;
+
+    /* Force a capture of the timer into 'cntr' capture channel; read it */
+    hwtimer->TASKS_CAPTURE[NRF_TIMER_CC_READ] = 1;
+    tcntr = hwtimer->CC[NRF_TIMER_CC_READ];
+
+    return tcntr;
+}
+
+/**
+ * nrf timer set ocmp
+ *
+ * Set the OCMP used by the timer to the desired expiration tick
+ *
+ * NOTE: Must be called with interrupts disabled.
+ *
+ * @param timer Pointer to timer.
+ */
+static void
+nrf_timer_set_ocmp(struct nrf51_hal_timer *bsptimer, uint32_t expiry)
+{
+    int32_t delta_t;
+    uint16_t expiry16;
+    uint32_t temp;
+    NRF_TIMER_Type *hwtimer;
+
+    hwtimer = bsptimer->tmr_reg;
+
+    /* Disable ocmp interrupt and set new value */
+    hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
+
+    if (bsptimer->tmr_16bit) {
+        temp = expiry & 0xffff0000;
+        delta_t = (int32_t)(temp - bsptimer->tmr_cntr);
+        if (delta_t < 0) {
+            goto set_ocmp_late;
+        } else if (delta_t == 0) {
+            /* Set ocmp and check if missed it */
+            expiry16 = (uint16_t) expiry;
+            hwtimer->CC[NRF_TIMER_CC_INT] = expiry16;
+
+            /* Clear interrupt flag */
+            hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT] = 0;
+
+            /* Enable the output compare interrupt */
+            hwtimer->INTENSET = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
+
+            /* Force interrupt to occur as we may have missed it */
+            if (nrf_read_timer_cntr(hwtimer) > expiry16) {
+                goto set_ocmp_late;
+            }
+        } else {
+            /* Nothing to do; wait for overflow interrupt to set ocmp */
+        }
+    } else {
+        /* Set output compare register to timer expiration */
+        hwtimer->CC[NRF_TIMER_CC_INT] = expiry;
+
+        /* Clear interrupt flag */
+        hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT] = 0;
+
+        /* Enable the output compare interrupt */
+        hwtimer->INTENSET = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
+
+        /* Force interrupt to occur as we may have missed it */
+        if ((int32_t)(nrf_read_timer_cntr(hwtimer) - expiry) >= 0) {
+            goto set_ocmp_late;
+        }
+    }
+    return;
+
+set_ocmp_late:
+    NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
+}
+
+
+/* Disable output compare used for timer */
+static void
+nrf_timer_disable_ocmp(NRF_TIMER_Type *hwtimer)
+{
+    hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
+}
+
+static uint32_t
+hal_timer_read_bsptimer(struct nrf51_hal_timer *bsptimer)
+{
+    uint16_t low;
+    uint32_t ctx;
+    uint32_t tcntr;
+    NRF_TIMER_Type *hwtimer;
+
+    if (bsptimer->tmr_16bit) {
+        hwtimer = bsptimer->tmr_reg;
+        __HAL_DISABLE_INTERRUPTS(ctx);
+        tcntr = bsptimer->tmr_cntr;
+        low = nrf_read_timer_cntr(hwtimer);
+        if (hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_OVERFLOW]) {
+            tcntr += 65536;
+            bsptimer->tmr_cntr = tcntr;
+            low = nrf_read_timer_cntr(hwtimer);
+            hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_OVERFLOW] = 0;
+            NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
+        }
+        tcntr |= low;
+        __HAL_ENABLE_INTERRUPTS(ctx);
+    } else {
+        /* Force a capture of the timer into 'cntr' capture channel; read it */
+        tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg);
+    }
+
+    return tcntr;
+}
+
+#if (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(TIMER_2))
+/**
+ * hal timer chk queue
+ *
+ *
+ * @param bsptimer
+ */
+static void
+hal_timer_chk_queue(struct nrf51_hal_timer *bsptimer)
+{
+    uint32_t tcntr;
+    uint32_t ctx;
+    struct hal_timer *timer;
+
+    /* disable interrupts */
+    __HAL_DISABLE_INTERRUPTS(ctx);
+    while ((timer = TAILQ_FIRST(&bsptimer->hal_timer_q)) != NULL) {
+        if (bsptimer->tmr_16bit) {
+            tcntr = hal_timer_read_bsptimer(bsptimer);
+        } else {
+            tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg);
+        }
+        if ((int32_t)(tcntr - timer->expiry) >= 0) {
+            TAILQ_REMOVE(&bsptimer->hal_timer_q, timer, link);
+            timer->link.tqe_prev = NULL;
+            timer->cb_func(timer->cb_arg);
+        } else {
+            break;
+        }
+    }
+
+    /* Any timers left on queue? If so, we need to set OCMP */
+    timer = TAILQ_FIRST(&bsptimer->hal_timer_q);
+    if (timer) {
+        nrf_timer_set_ocmp(bsptimer, timer->expiry);
+    } else {
+        nrf_timer_disable_ocmp(bsptimer->tmr_reg);
+    }
+    __HAL_ENABLE_INTERRUPTS(ctx);
+}
+
+#endif
+
+/**
+ * hal timer irq handler
+ *
+ * Generic HAL timer irq handler.
+ *
+ * @param tmr
+ */
+/**
+ * hal timer irq handler
+ *
+ * This is the global timer interrupt routine.
+ *
+ */
+#if (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(TIMER_2))
+
+static void
+hal_timer_irq_handler(struct nrf51_hal_timer *bsptimer)
+{
+    uint32_t overflow;
+    uint32_t compare;
+    NRF_TIMER_Type *hwtimer;
+
+    /* Check interrupt source. If set, clear them */
+    hwtimer = bsptimer->tmr_reg;
+    compare = hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT];
+    if (compare) {
+        hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT] = 0;
+    }
+
+    if (bsptimer->tmr_16bit) {
+        overflow = hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_OVERFLOW];
+        if (overflow) {
+            hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_OVERFLOW] = 0;
+            bsptimer->tmr_cntr += 65536;
+        }
+    }
+
+
+    /* Count # of timer isrs */
+    ++bsptimer->timer_isrs;
+
+    /*
+     * NOTE: we dont check the 'compare' variable here due to how the timer
+     * is implemented on this chip. There is no way to force an output
+     * compare, so if we are late setting the output compare (i.e. the timer
+     * counter is already passed the output compare value), we use the NVIC
+     * to set a pending interrupt. This means that there will be no compare
+     * flag set, so all we do is check to see if the compare interrupt is
+     * enabled.
+     */
+    hal_timer_chk_queue(bsptimer);
+
+    /* Recommended by nordic to make sure interrupts are cleared */
+    compare = hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT];
+}
+#endif
+
+#if MYNEWT_VAL(TIMER_0)
+void
+nrf51_timer0_irq_handler(void)
+{
+    hal_timer_irq_handler(&nrf51_hal_timer0);
+}
+#endif
+
+#if MYNEWT_VAL(TIMER_1)
+void
+nrf51_timer1_irq_handler(void)
+{
+    hal_timer_irq_handler(&nrf51_hal_timer1);
+}
+#endif
+
+#if MYNEWT_VAL(TIMER_2)
+void
+nrf51_timer2_irq_handler(void)
+{
+    hal_timer_irq_handler(&nrf51_hal_timer2);
+}
+#endif
+
+/**
+ * hal timer init
+ *
+ * Initialize (and start) a timer to run at the desired frequency.
+ *
+ * @param timer_num
+ * @param freq_hz
+ *
+ * @return int
+ */
+int
+hal_timer_init(int timer_num, uint32_t freq_hz)
+{
+    int rc;
+    uint8_t prescaler;
+    uint8_t irq_num;
+    uint32_t ctx;
+    uint32_t div;
+    uint32_t min_delta;
+    uint32_t max_delta;
+    uint32_t prio;
+    struct nrf51_hal_timer *bsptimer;
+    NRF_TIMER_Type *hwtimer;
+    hal_timer_irq_handler_t irq_isr;
+
+    NRF51_HAL_TIMER_RESOLVE(timer_num, bsptimer);
+
+    /* Set timer to desired frequency */
+    div = NRF51_MAX_TIMER_FREQ / freq_hz;
+
+    /* Largest prescaler is 2^9 and must make sure frequency not too high */
+    if (bsptimer->tmr_enabled || (div == 0) || (div > 512)) {
+        rc = EINVAL;
+        goto err;
+    }
+
+    if (div == 1) {
+        prescaler = 0;
+    } else {
+        /* Find closest prescaler */
+        for (prescaler = 1; prescaler < 10; ++prescaler) {
+            if (div <= (1 << prescaler)) {
+                min_delta = div - (1 << (prescaler - 1));
+                max_delta = (1 << prescaler) - div;
+                if (min_delta < max_delta) {
+                    prescaler -= 1;
+                }
+                break;
+            }
+        }
+    }
+
+    /* Now set the actual frequency */
+    bsptimer->tmr_freq = NRF51_MAX_TIMER_FREQ / (1 << prescaler);
+
+    switch (timer_num) {
+#if MYNEWT_VAL(TIMER_0)
+    case 0:
+        irq_num = TIMER0_IRQn;
+        hwtimer = NRF_TIMER0;
+        irq_isr = nrf51_timer0_irq_handler;
+        prio = MYNEWT_VAL(TIMER_0_INTERRUPT_PRIORITY);
+        break;
+#endif
+#if MYNEWT_VAL(TIMER_1)
+    case 1:
+        irq_num = TIMER1_IRQn;
+        hwtimer = NRF_TIMER1;
+        irq_isr = nrf51_timer1_irq_handler;
+        bsptimer->tmr_16bit = 1;
+        prio = MYNEWT_VAL(TIMER_1_INTERRUPT_PRIORITY);
+        break;
+#endif
+#if MYNEWT_VAL(TIMER_2)
+    case 2:
+        irq_num = TIMER2_IRQn;
+        hwtimer = NRF_TIMER2;
+        irq_isr = nrf51_timer2_irq_handler;
+        bsptimer->tmr_16bit = 1;
+        prio = MYNEWT_VAL(TIMER_2_INTERRUPT_PRIORITY);
+        break;
+#endif
+    default:
+        prio = 0;
+        hwtimer = NULL;
+        break;
+    }
+
+    if (hwtimer == NULL) {
+        rc = EINVAL;
+        goto err;
+    }
+
+    bsptimer->tmr_reg = hwtimer;
+    bsptimer->tmr_irq_num = irq_num;
+    bsptimer->tmr_enabled = 1;
+
+    /* disable interrupts */
+    __HAL_DISABLE_INTERRUPTS(ctx);
+
+    /* XXX: only do this if it is HFCLK */
+    /* Make sure HFXO is started */
+    if ((NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) == 0) {
+        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
+        NRF_CLOCK->TASKS_HFCLKSTART = 1;
+        while (1) {
+            if ((NRF_CLOCK->EVENTS_HFCLKSTARTED) != 0) {
+                break;
+            }
+        }
+    }
+
+    /* Stop the timer first */
+    hwtimer->TASKS_STOP = 1;
+
+    /* Set the pre-scalar */
+    hwtimer->PRESCALER = prescaler;
+
+    /* Put the timer in timer mode using 32 bits. */
+    hwtimer->MODE = TIMER_MODE_MODE_Timer;
+
+    if (bsptimer->tmr_16bit) {
+        hwtimer->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
+        hwtimer->CC[NRF_TIMER_CC_OVERFLOW] = 0;
+        hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_OVERFLOW] = 0;
+        hwtimer->INTENSET = NRF_TIMER_INT_MASK(NRF_TIMER_CC_OVERFLOW);
+    } else {
+        hwtimer->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
+    }
+
+    /* Start the timer */
+    hwtimer->TASKS_START = 1;
+
+    /* Set isr in vector table and enable interrupt */
+    NVIC_SetPriority(irq_num, prio);
+    NVIC_SetVector(irq_num, (uint32_t)irq_isr);
+    NVIC_EnableIRQ(irq_num);
+
+    __HAL_ENABLE_INTERRUPTS(ctx);
+
+    hwtimer->PRESCALER = prescaler;
+
+    return 0;
+
+err:
+    return rc;
+}
+
+/**
+ * hal timer deinit
+ *
+ * De-initialize a HW timer.
+ *
+ * @param timer_num
+ *
+ * @return int
+ */
+int
+hal_timer_deinit(int timer_num)
+{
+    int rc;
+    uint32_t ctx;
+    struct nrf51_hal_timer *bsptimer;
+    NRF_TIMER_Type *hwtimer;
+
+    NRF51_HAL_TIMER_RESOLVE(timer_num, bsptimer);
+
+    __HAL_DISABLE_INTERRUPTS(ctx);
+    hwtimer = bsptimer->tmr_reg;
+    hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
+    hwtimer->TASKS_STOP = 1;
+    __HAL_ENABLE_INTERRUPTS(ctx);
+
+    bsptimer->tmr_enabled = 0;
+
+err:
+    return rc;
+}
+
+/**
+ * hal timer get resolution
+ *
+ * Get the resolution of the timer. This is the timer period, in nanoseconds
+ *
+ * @param timer_num
+ *
+ * @return uint32_t The
+ */
+uint32_t
+hal_timer_get_resolution(int timer_num)
+{
+    int rc;
+    uint32_t resolution;
+    struct nrf51_hal_timer *bsptimer;
+
+    NRF51_HAL_TIMER_RESOLVE(timer_num, bsptimer);
+
+    resolution = 1000000000 / bsptimer->tmr_freq;
+    return resolution;
+
+err:
+    rc = 0;
+    return rc;
+}
+
+/**
+ * hal timer read
+ *
+ * Returns the timer counter. NOTE: if the timer is a 16-bit timer, only
+ * the lower 16 bits are valid. If the timer is a 64-bit timer, only the
+ * low 32-bits are returned.
+ *
+ * @return uint32_t The timer counter register.
+ */
+uint32_t
+hal_timer_read(int timer_num)
+{
+    int rc;
+    uint32_t tcntr;
+    struct nrf51_hal_timer *bsptimer;
+
+    NRF51_HAL_TIMER_RESOLVE(timer_num, bsptimer);
+    tcntr = hal_timer_read_bsptimer(bsptimer);
+    return tcntr;
+
+    /* Assert here since there is no invalid return code */
+err:
+    assert(0);
+    rc = 0;
+    return rc;
+}
+
+/**
+ * hal timer delay
+ *
+ * Blocking delay for n ticks
+ *
+ * @param timer_num
+ * @param ticks
+ *
+ * @return int 0 on success; error code otherwise.
+ */
+int
+hal_timer_delay(int timer_num, uint32_t ticks)
+{
+    uint32_t until;
+
+    until = hal_timer_read(timer_num) + ticks;
+    while ((int32_t)(hal_timer_read(timer_num) - until) <= 0) {
+        /* Loop here till finished */
+    }
+
+    return 0;
+}
+
+/**
+ *
+ * Initialize the HAL timer structure with the callback and the callback
+ * argument. Also initializes the HW specific timer pointer.
+ *
+ * @param cb_func
+ *
+ * @return int
+ */
+int
+hal_timer_set_cb(int timer_num, struct hal_timer *timer, hal_timer_cb cb_func,
+                 void *arg)
+{
+    int rc;
+    struct nrf51_hal_timer *bsptimer;
+
+    NRF51_HAL_TIMER_RESOLVE(timer_num, bsptimer);
+
+    timer->cb_func = cb_func;
+    timer->cb_arg = arg;
+    timer->link.tqe_prev = NULL;
+    timer->bsp_timer = bsptimer;
+
+    rc = 0;
+
+err:
+    return rc;
+}
+
+int
+hal_timer_start(struct hal_timer *timer, uint32_t ticks)
+{
+    int rc;
+    uint32_t tick;
+    struct nrf51_hal_timer *bsptimer;
+
+    /* Set the tick value at which the timer should expire */
+    if (ticks) {
+        bsptimer = (struct nrf51_hal_timer *)timer->bsp_timer;
+        tick = hal_timer_read_bsptimer(bsptimer) + ticks;
+        rc = hal_timer_start_at(timer, tick);
+    } else {
+        rc = EINVAL;
+    }
+    return rc;
+}
+
+int
+hal_timer_start_at(struct hal_timer *timer, uint32_t tick)
+{
+    uint32_t ctx;
+    struct hal_timer *entry;
+    struct nrf51_hal_timer *bsptimer;
+
+    if ((timer == NULL) || (timer->link.tqe_prev != NULL) ||
+        (timer->cb_func == NULL)) {
+        return EINVAL;
+    }
+    bsptimer = (struct nrf51_hal_timer *)timer->bsp_timer;
+    timer->expiry = tick;
+
+    __HAL_DISABLE_INTERRUPTS(ctx);
+
+    if (TAILQ_EMPTY(&bsptimer->hal_timer_q)) {
+        TAILQ_INSERT_HEAD(&bsptimer->hal_timer_q, timer, link);
+    } else {
+        TAILQ_FOREACH(entry, &bsptimer->hal_timer_q, link) {
+            if ((int32_t)(timer->expiry - entry->expiry) < 0) {
+                TAILQ_INSERT_BEFORE(entry, timer, link);
+                break;
+            }
+        }
+        if (!entry) {
+            TAILQ_INSERT_TAIL(&bsptimer->hal_timer_q, timer, link);
+        }
+    }
+
+    /* If this is the head, we need to set new OCMP */
+    if (timer == TAILQ_FIRST(&bsptimer->hal_timer_q)) {
+        nrf_timer_set_ocmp(bsptimer, timer->expiry);
+    }
+
+    __HAL_ENABLE_INTERRUPTS(ctx);
+
+    return 0;
+}
+
+/**
+ * hal timer stop
+ *
+ * Stop a timer.
+ *
+ * @param timer
+ *
+ * @return int
+ */
+int
+hal_timer_stop(struct hal_timer *timer)
+{
+    uint32_t ctx;
+    int reset_ocmp;
+    struct hal_timer *entry;
+    struct nrf51_hal_timer *bsptimer;
+
+    if (timer == NULL) {
+        return EINVAL;
+    }
+
+   bsptimer = (struct nrf51_hal_timer *)timer->bsp_timer;
+
+    __HAL_DISABLE_INTERRUPTS(ctx);
+
+    if (timer->link.tqe_prev != NULL) {
+        reset_ocmp = 0;
+        if (timer == TAILQ_FIRST(&bsptimer->hal_timer_q)) {
+            /* If first on queue, we will need to reset OCMP */
+            entry = TAILQ_NEXT(timer, link);
+            reset_ocmp = 1;
+        }
+        TAILQ_REMOVE(&bsptimer->hal_timer_q, timer, link);
+        timer->link.tqe_prev = NULL;
+        if (reset_ocmp) {
+            if (entry) {
+                nrf_timer_set_ocmp((struct nrf51_hal_timer *)entry->bsp_timer,
+                                   entry->expiry);
+            } else {
+                nrf_timer_disable_ocmp(bsptimer->tmr_reg);
+            }
+        }
+    }
+
+    __HAL_ENABLE_INTERRUPTS(ctx);
+
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3cb38e68/hw/mcu/nordic/nrf52xxx/src/hal_timer.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_timer.c b/hw/mcu/nordic/nrf52xxx/src/hal_timer.c
index 6d43409..ed15ffb 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_timer.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_timer.c
@@ -313,6 +313,7 @@ hal_timer_init(int timer_num, uint32_t freq_hz)
     uint32_t div;
     uint32_t min_delta;
     uint32_t max_delta;
+    uint32_t prio;
     struct nrf52_hal_timer *bsptimer;
     NRF_TIMER_Type *hwtimer;
     hal_timer_irq_handler_t irq_isr;
@@ -353,6 +354,7 @@ hal_timer_init(int timer_num, uint32_t freq_hz)
         irq_num = TIMER0_IRQn;
         hwtimer = NRF_TIMER0;
         irq_isr = nrf52_timer0_irq_handler;
+        prio = MYNEWT_VAL(TIMER_0_INTERRUPT_PRIORITY);
         break;
 #endif
 #if MYNEWT_VAL(TIMER_1)
@@ -360,6 +362,7 @@ hal_timer_init(int timer_num, uint32_t freq_hz)
         irq_num = TIMER1_IRQn;
         hwtimer = NRF_TIMER1;
         irq_isr = nrf52_timer1_irq_handler;
+        prio = MYNEWT_VAL(TIMER_1_INTERRUPT_PRIORITY);
         break;
 #endif
 #if MYNEWT_VAL(TIMER_2)
@@ -367,6 +370,7 @@ hal_timer_init(int timer_num, uint32_t freq_hz)
         irq_num = TIMER2_IRQn;
         hwtimer = NRF_TIMER2;
         irq_isr = nrf52_timer2_irq_handler;
+        prio = MYNEWT_VAL(TIMER_2_INTERRUPT_PRIORITY);
         break;
 #endif
 #if MYNEWT_VAL(TIMER_3)
@@ -374,6 +378,7 @@ hal_timer_init(int timer_num, uint32_t freq_hz)
         irq_num = TIMER3_IRQn;
         hwtimer = NRF_TIMER3;
         irq_isr = nrf52_timer3_irq_handler;
+        prio = MYNEWT_VAL(TIMER_3_INTERRUPT_PRIORITY);
         break;
 #endif
 #if MYNEWT_VAL(TIMER_4)
@@ -381,10 +386,12 @@ hal_timer_init(int timer_num, uint32_t freq_hz)
         irq_num = TIMER4_IRQn;
         hwtimer = NRF_TIMER4;
         irq_isr = nrf52_timer4_irq_handler;
+        prio = MYNEWT_VAL(TIMER_4_INTERRUPT_PRIORITY);
         break;
 #endif
     default:
         hwtimer = NULL;
+        prio = 0;
         break;
     }
 
@@ -400,6 +407,17 @@ hal_timer_init(int timer_num, uint32_t freq_hz)
     /* disable interrupts */
     __HAL_DISABLE_INTERRUPTS(ctx);
 
+    /* Make sure HFXO is started */
+    if ((NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) == 0) {
+        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
+        NRF_CLOCK->TASKS_HFCLKSTART = 1;
+        while (1) {
+            if ((NRF_CLOCK->EVENTS_HFCLKSTARTED) != 0) {
+                break;
+            }
+        }
+    }
+
     /* Stop the timer first */
     hwtimer->TASKS_STOP = 1;
 
@@ -414,6 +432,7 @@ hal_timer_init(int timer_num, uint32_t freq_hz)
     hwtimer->TASKS_START = 1;
 
     /* Set isr in vector table and enable interrupt */
+    NVIC_SetPriority(irq_num, prio);
     NVIC_SetVector(irq_num, (uint32_t)irq_isr);
     NVIC_EnableIRQ(irq_num);
 


[2/2] incubator-mynewt-core git commit: Fix build issues with changes to syscfg.

Posted by we...@apache.org.
Fix build issues with changes to syscfg.


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/ba4aa33b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/ba4aa33b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/ba4aa33b

Branch: refs/heads/develop
Commit: ba4aa33b0b3210858c7a4091c66c9ee69547f402
Parents: ab85825
Author: William San Filippo <wi...@runtime.io>
Authored: Tue Oct 4 17:43:21 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Wed Oct 5 20:47:10 2016 -0700

----------------------------------------------------------------------
 apps/bletest/src/main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ba4aa33b/apps/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletest/src/main.c b/apps/bletest/src/main.c
index 13bcdfa..09969cb 100755
--- a/apps/bletest/src/main.c
+++ b/apps/bletest/src/main.c
@@ -617,7 +617,7 @@ bletest_get_packet(void)
     struct os_mbuf *om;
 
     om = NULL;
-    if (g_mbuf_pool.omp_pool->mp_num_free >= 5) {
+    if (os_msys_num_free() >= 5) {
         om = os_msys_get_pkthdr(BLE_MBUF_PAYLOAD_SIZE,
                                 sizeof(struct ble_mbuf_hdr));
     }
@@ -630,7 +630,7 @@ bletest_execute_advertiser(void)
     int i;
 #if (BLETEST_CONCURRENT_CONN_TEST == 1)
     int j;
-#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1)
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
     uint16_t mask;
     uint16_t reply_handle;
 #endif