You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by an...@apache.org on 2022/02/04 13:25:54 UTC

[mynewt-nimble] branch master updated (b46b2b4 -> 7cac65c)

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

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


    from b46b2b4  nimble/plna: Fix bypass on SKY66112
     new 22b38cc  nimble/ll: Add ll_tmr
     new 7cac65c  nimble/ll: Add support for non-32768 os_cputime freq

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


Summary of changes:
 nimble/controller/include/controller/ble_ll.h      |  18 +--
 .../controller/include/controller/ble_ll_rfmgmt.h  |   4 +-
 nimble/controller/include/controller/ble_ll_scan.h |   4 +-
 .../controller/include/controller/ble_ll_sched.h   |   1 -
 nimble/controller/include/controller/ble_ll_tmr.h  | 169 +++++++++++++++++++++
 nimble/controller/src/ble_ll.c                     |   1 -
 nimble/controller/src/ble_ll_adv.c                 |  96 ++++++------
 nimble/controller/src/ble_ll_conn.c                | 107 +++++--------
 nimble/controller/src/ble_ll_ctrl.c                |   4 +-
 nimble/controller/src/ble_ll_dtm.c                 |  19 +--
 nimble/controller/src/ble_ll_rfmgmt.c              |  26 ++--
 nimble/controller/src/ble_ll_scan.c                |  32 ++--
 nimble/controller/src/ble_ll_sched.c               | 147 +++++++-----------
 nimble/controller/src/ble_ll_sync.c                |  52 ++-----
 nimble/controller/src/ble_ll_utils.c               |   3 +-
 nimble/controller/syscfg.yml                       |   1 -
 nimble/drivers/nrf52/src/ble_phy.c                 |   2 +
 17 files changed, 370 insertions(+), 316 deletions(-)
 create mode 100644 nimble/controller/include/controller/ble_ll_tmr.h

[mynewt-nimble] 02/02: nimble/ll: Add support for non-32768 os_cputime freq

Posted by an...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 7cac65c0ecd55179fcd70a5305c7ac1f3e79968f
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Fri Jan 28 14:41:18 2022 +0100

    nimble/ll: Add support for non-32768 os_cputime freq
    
    This removes restrictions to force 32768Hz clock for os_cputime and
    uses explicit convertions from usecs to ticks instead of precalculated
    values.
---
 nimble/controller/include/controller/ble_ll.h      |  4 ----
 .../controller/include/controller/ble_ll_sched.h   |  1 -
 nimble/controller/include/controller/ble_ll_tmr.h  | 12 ++++++++++-
 nimble/controller/src/ble_ll_conn.c                |  8 +++++---
 nimble/controller/src/ble_ll_sched.c               | 23 +++++++++++-----------
 nimble/controller/syscfg.yml                       |  1 -
 6 files changed, 28 insertions(+), 21 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h
index d148fbe..c51d410 100644
--- a/nimble/controller/include/controller/ble_ll.h
+++ b/nimble/controller/include/controller/ble_ll.h
@@ -37,10 +37,6 @@
 extern "C" {
 #endif
 
-#if MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768
-#error 32.768kHz clock required
-#endif
-
 #if defined(MYNEWT) && MYNEWT_VAL(BLE_LL_HCI_VS_EVENT_ON_ASSERT)
 #ifdef NDEBUG
 #define BLE_LL_ASSERT(cond) (void(0))
diff --git a/nimble/controller/include/controller/ble_ll_sched.h b/nimble/controller/include/controller/ble_ll_sched.h
index 45e148c..4ce687e 100644
--- a/nimble/controller/include/controller/ble_ll_sched.h
+++ b/nimble/controller/include/controller/ble_ll_sched.h
@@ -26,7 +26,6 @@ extern "C" {
 
 /* Time per BLE scheduler slot */
 #define BLE_LL_SCHED_USECS_PER_SLOT   (1250)
-#define BLE_LL_SCHED_TICKS_PER_SLOT   (41)    /* 1 tick = 30.517 usecs */
 
 /*
  * Worst case time needed for scheduled advertising item. This is the longest
diff --git a/nimble/controller/include/controller/ble_ll_tmr.h b/nimble/controller/include/controller/ble_ll_tmr.h
index 9dd6ab4..2d79427 100644
--- a/nimble/controller/include/controller/ble_ll_tmr.h
+++ b/nimble/controller/include/controller/ble_ll_tmr.h
@@ -27,7 +27,8 @@
 extern "C" {
 #endif
 
-#define USECS_PER_TICK          (31)
+#define USECS_PER_TICK      ((1000000 + MYNEWT_VAL(OS_CPUTIME_FREQ) - 1) / \
+                             MYNEWT_VAL(OS_CPUTIME_FREQ))
 
 #define LL_TMR_LT(_t1, _t2)     ((int32_t)((_t1) - (_t2)) < 0)
 #define LL_TMR_GT(_t1, _t2)     ((int32_t)((_t1) - (_t2)) > 0)
@@ -49,15 +50,24 @@ ble_ll_tmr_get(void)
 static inline uint32_t
 ble_ll_tmr_t2u(uint32_t ticks)
 {
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 31250
+    return ticks * 32;
+#endif
+
     return os_cputime_ticks_to_usecs(ticks);
 }
 
 static inline uint32_t
 ble_ll_tmr_u2t(uint32_t usecs)
 {
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 31250
+    return usecs / 32;
+#endif
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
     if (usecs <= 31249) {
         return (usecs * 137439) / 4194304;
     }
+#endif
 
     return os_cputime_usecs_to_ticks(usecs);
 }
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index d3579ed..7e3baab 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -2222,7 +2222,8 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
 #if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
     itvl = g_ble_ll_sched_data.sch_ticks_per_period;
 #else
-    itvl = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_TICKS_PER_SLOT;
+    itvl = ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) *
+                          BLE_LL_SCHED_USECS_PER_SLOT);
 #endif
 #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL)
     if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
@@ -2339,8 +2340,9 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
 
 #else
         connsm->ce_end_time = connsm->anchor_point +
-            (MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_TICKS_PER_SLOT)
-            + ble_ll_tmr_u2t(connsm->slave_cur_tx_win_usecs) + 1;
+                              ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) *
+                                             BLE_LL_SCHED_USECS_PER_SLOT +
+                                             connsm->slave_cur_tx_win_usecs) + 1;
 #endif
         connsm->slave_cur_window_widening = BLE_LL_JITTER_USECS;
 
diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c
index 94b45e8..0ba6a89 100644
--- a/nimble/controller/src/ble_ll_sched.c
+++ b/nimble/controller/src/ble_ll_sched.c
@@ -718,7 +718,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
          * We received packet on advertising channel which means this is a legacy
          * PDU on 1 Mbps - we do as described above.
          */
-        earliest_start = adv_rxend + 57;
+        earliest_start = adv_rxend + ble_ll_tmr_u2t(1752);
     } else {
         /*
          * The calculations are similar as above.
@@ -731,27 +731,28 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
          *
          */
         if (ble_hdr->rxinfo.phy == BLE_PHY_1M) {
-            // 150 + 352 + 2500 = 3002us = 98.37 ticks
-            earliest_start = adv_rxend + 98;
+            /* 150 + 352 + 2500 = 3002us */
+            earliest_start = adv_rxend + ble_ll_tmr_u2t(3002);
         } else if (ble_hdr->rxinfo.phy == BLE_PHY_2M) {
-            // 150 + 180 + 2500 = 2830us = 92.73 ticks
-            earliest_start = adv_rxend + 93;
+            /* 150 + 180 + 2500 = 2830us */
+            earliest_start = adv_rxend + ble_ll_tmr_u2t(2830);
         } else if (ble_hdr->rxinfo.phy == BLE_PHY_CODED) {
-            // 150 + 2896 + 3750 = 6796us = 222.69 ticks
-            earliest_start = adv_rxend + 223;
+            /* 150 + 2896 + 3750 = 6796us */
+            earliest_start = adv_rxend + ble_ll_tmr_u2t(6796);
         } else {
             BLE_LL_ASSERT(0);
         }
     }
 
     sch->start_time = earliest_start - g_ble_ll_sched_offset_ticks;
-    sch->end_time = earliest_start + MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) *
-                                     BLE_LL_SCHED_TICKS_PER_SLOT;
+    sch->end_time = earliest_start +
+                    ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) *
+                                   BLE_LL_SCHED_USECS_PER_SLOT);
 
     orig_start_time = sch->start_time;
 
-    min_win_offset = MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) *
-                     BLE_LL_SCHED_TICKS_PER_SLOT;
+    min_win_offset = ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) *
+                                    BLE_LL_SCHED_USECS_PER_SLOT);
     sch->start_time += min_win_offset;
     sch->end_time += min_win_offset;
 
diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml
index bb46311..9f17350 100644
--- a/nimble/controller/syscfg.yml
+++ b/nimble/controller/syscfg.yml
@@ -516,7 +516,6 @@ syscfg.vals.!BLE_HOST:
     BLE_LL_HCI_VS_EVENT_ON_ASSERT: 1
 
 syscfg.restrictions:
-    - OS_CPUTIME_FREQ == 32768
     - BLE_LL_PUBLIC_DEV_ADDR <= 0xffffffffffff
     - BLE_LL_PA == 0 || BLE_LL_PA_GPIO >= 0
     - BLE_LL_LNA == 0 || BLE_LL_LNA_GPIO >= 0

[mynewt-nimble] 01/02: nimble/ll: Add ll_tmr

Posted by an...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 22b38ccab9bb037ab5738a250cb21660d6a65248
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Fri Jan 28 00:43:20 2022 +0100

    nimble/ll: Add ll_tmr
    
    This adds generic API for LL timer which replaces explicit os_cputime
    usage in LL.
    
    Short term, this allows for more consistent and simpler code since new
    API introduces few helpers to perform add/sub operations on timers with
    proper usecs wrapping.
    
    Long term, this will allow LL to work natively with timers that are not
    based on 32768Hz clock, as e.g. Dialog CMAC.
---
 nimble/controller/include/controller/ble_ll.h      |  14 +-
 .../controller/include/controller/ble_ll_rfmgmt.h  |   4 +-
 nimble/controller/include/controller/ble_ll_scan.h |   4 +-
 nimble/controller/include/controller/ble_ll_tmr.h  | 159 +++++++++++++++++++++
 nimble/controller/src/ble_ll.c                     |   1 -
 nimble/controller/src/ble_ll_adv.c                 |  96 ++++++-------
 nimble/controller/src/ble_ll_conn.c                | 101 +++++--------
 nimble/controller/src/ble_ll_ctrl.c                |   4 +-
 nimble/controller/src/ble_ll_dtm.c                 |  19 +--
 nimble/controller/src/ble_ll_rfmgmt.c              |  26 ++--
 nimble/controller/src/ble_ll_scan.c                |  32 ++---
 nimble/controller/src/ble_ll_sched.c               | 124 ++++++----------
 nimble/controller/src/ble_ll_sync.c                |  52 +++----
 nimble/controller/src/ble_ll_utils.c               |   3 +-
 nimble/drivers/nrf52/src/ble_phy.c                 |   2 +
 15 files changed, 344 insertions(+), 297 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h
index f4b8517..d148fbe 100644
--- a/nimble/controller/include/controller/ble_ll.h
+++ b/nimble/controller/include/controller/ble_ll.h
@@ -21,7 +21,6 @@
 #define H_BLE_LL_
 
 #include "stats/stats.h"
-#include "os/os_cputime.h"
 #include "nimble/nimble_opt.h"
 #include "nimble/nimble_npl.h"
 #include "controller/ble_phy.h"
@@ -30,6 +29,9 @@
 #include "controller/ble_ll_ctrl.h"
 #include "hal/hal_system.h"
 #endif
+#ifdef RIOT_VERSION
+#include "hal/hal_timer.h"
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -123,9 +125,6 @@ struct ble_ll_obj
     /* Task event queue */
     struct ble_npl_eventq ll_evq;
 
-    /* Wait for response timer */
-    struct hal_timer ll_wfr_timer;
-
     /* Packet receive queue (and event). Holds received packets from PHY */
     struct ble_npl_event ll_rx_pkt_ev;
     struct ble_ll_pkt_q ll_rx_pkt_q;
@@ -612,13 +611,6 @@ ble_ll_get_addr_type(uint8_t txrxflag)
     return BLE_HCI_ADV_OWN_ADDR_PUBLIC;
 }
 
-/* Convert usecs to ticks and round up to nearest tick */
-static inline uint32_t
-ble_ll_usecs_to_ticks_round_up(uint32_t usecs)
-{
-    return os_cputime_usecs_to_ticks(usecs + 30);
-}
-
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
 /* LTK 0x4C68384139F574D836BCF34E9DFB01BF */
 extern const uint8_t g_bletest_LTK[];
diff --git a/nimble/controller/include/controller/ble_ll_rfmgmt.h b/nimble/controller/include/controller/ble_ll_rfmgmt.h
index 5e2d636..1aa1c4b 100644
--- a/nimble/controller/include/controller/ble_ll_rfmgmt.h
+++ b/nimble/controller/include/controller/ble_ll_rfmgmt.h
@@ -24,6 +24,8 @@
 extern "C" {
 #endif
 
+#include "controller/ble_ll_tmr.h"
+
 void ble_ll_rfmgmt_init(void);
 
 #if MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME) > 0
@@ -51,7 +53,7 @@ static inline void ble_ll_rfmgmt_reset(void) { }
 static inline void ble_ll_rfmgmt_scan_changed(bool e, uint32_t n) { }
 static inline void ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *f) { }
 static inline void ble_ll_rfmgmt_release(void) { }
-static inline uint32_t ble_ll_rfmgmt_enable_now(void) { return os_cputime_get32(); }
+static inline uint32_t ble_ll_rfmgmt_enable_now(void) { return ble_ll_tmr_get(); }
 static inline bool ble_ll_rfmgmt_is_enabled(void) { return true; }
 
 #endif
diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h
index a44e431..34bcd60 100644
--- a/nimble/controller/include/controller/ble_ll_scan.h
+++ b/nimble/controller/include/controller/ble_ll_scan.h
@@ -21,7 +21,7 @@
 #define H_BLE_LL_SCAN_
 
 #include "controller/ble_ll_sched.h"
-#include "hal/hal_timer.h"
+#include "controller/ble_ll_tmr.h"
 #include "syscfg/syscfg.h"
 #include "nimble/nimble_npl.h"
 
@@ -135,7 +135,7 @@ struct ble_ll_scan_sm
     uint16_t backoff_count;
     uint32_t scan_win_start_time;
     struct ble_npl_event scan_sched_ev;
-    struct hal_timer scan_timer;
+    struct ble_ll_tmr scan_timer;
     struct ble_npl_event scan_interrupted_ev;
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
diff --git a/nimble/controller/include/controller/ble_ll_tmr.h b/nimble/controller/include/controller/ble_ll_tmr.h
new file mode 100644
index 0000000..9dd6ab4
--- /dev/null
+++ b/nimble/controller/include/controller/ble_ll_tmr.h
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_BLE_LL_TMR_
+#define H_BLE_LL_TMR_
+
+#include "os/os_cputime.h"
+#include "controller/ble_ll.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define USECS_PER_TICK          (31)
+
+#define LL_TMR_LT(_t1, _t2)     ((int32_t)((_t1) - (_t2)) < 0)
+#define LL_TMR_GT(_t1, _t2)     ((int32_t)((_t1) - (_t2)) > 0)
+#define LL_TMR_GEQ(_t1, _t2)    ((int32_t)((_t1) - (_t2)) >= 0)
+#define LL_TMR_LEQ(_t1, _t2)    ((int32_t)((_t1) - (_t2)) <= 0)
+
+typedef void (ble_ll_tmr_cb)(void *arg);
+
+struct ble_ll_tmr {
+    struct hal_timer t;
+};
+
+static inline uint32_t
+ble_ll_tmr_get(void)
+{
+    return os_cputime_get32();
+}
+
+static inline uint32_t
+ble_ll_tmr_t2u(uint32_t ticks)
+{
+    return os_cputime_ticks_to_usecs(ticks);
+}
+
+static inline uint32_t
+ble_ll_tmr_u2t(uint32_t usecs)
+{
+    if (usecs <= 31249) {
+        return (usecs * 137439) / 4194304;
+    }
+
+    return os_cputime_usecs_to_ticks(usecs);
+}
+
+static inline uint32_t
+ble_ll_tmr_u2t_up(uint32_t usecs)
+{
+    return ble_ll_tmr_u2t(usecs + (USECS_PER_TICK - 1));
+}
+
+static inline uint32_t
+ble_ll_tmr_u2t_r(uint32_t usecs, uint8_t *rem_us)
+{
+    uint32_t ticks;
+
+    ticks = ble_ll_tmr_u2t(usecs);
+    *rem_us = usecs - ble_ll_tmr_t2u(ticks);
+    if (*rem_us == USECS_PER_TICK) {
+        *rem_us = 0;
+        ticks++;
+    }
+
+    return ticks;
+}
+
+static inline void
+ble_ll_tmr_add(uint32_t *ticks, uint8_t *rem_us, uint32_t usecs)
+{
+    uint32_t t_ticks;
+    uint8_t t_rem_us;
+
+    t_ticks = ble_ll_tmr_u2t_r(usecs, &t_rem_us);
+
+    *ticks += t_ticks;
+    *rem_us += t_rem_us;
+    if (*rem_us >= USECS_PER_TICK) {
+        *rem_us -= USECS_PER_TICK;
+        *ticks += 1;
+    }
+}
+
+static inline void
+ble_ll_tmr_add_u(uint32_t *ticks, uint8_t *rem_us, uint8_t usecs)
+{
+    BLE_LL_ASSERT(usecs < USECS_PER_TICK);
+
+    *rem_us += usecs;
+    if (*rem_us >= USECS_PER_TICK) {
+        *rem_us -= USECS_PER_TICK;
+        *ticks += 1;
+    }
+}
+
+static inline void
+ble_ll_tmr_sub(uint32_t *ticks, uint8_t *rem_us, uint32_t usecs)
+{
+    uint32_t t_ticks;
+    uint8_t t_rem_us;
+
+    if (usecs <= *rem_us) {
+        *rem_us -= usecs;
+        return;
+    }
+
+    usecs -= *rem_us;
+    *rem_us = 0;
+
+    t_ticks = ble_ll_tmr_u2t_r(usecs, &t_rem_us);
+    if (t_rem_us) {
+        t_ticks += 1;
+        *rem_us = USECS_PER_TICK - t_rem_us;
+    }
+
+    *ticks -= t_ticks;
+}
+
+static inline void
+ble_ll_tmr_init(struct ble_ll_tmr *tmr, ble_ll_tmr_cb *cb, void *arg)
+{
+    os_cputime_timer_init(&tmr->t, cb, arg);
+}
+
+static inline void
+ble_ll_tmr_start(struct ble_ll_tmr *tmr, uint32_t tgt)
+{
+    os_cputime_timer_start(&tmr->t, tgt);
+}
+
+static inline void
+ble_ll_tmr_stop(struct ble_ll_tmr *tmr)
+{
+    os_cputime_timer_stop(&tmr->t);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_BLE_LL_TMR_ */
\ No newline at end of file
diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c
index ce82c0d..34c0c77 100644
--- a/nimble/controller/src/ble_ll.c
+++ b/nimble/controller/src/ble_ll.c
@@ -24,7 +24,6 @@
 #include "sysinit/sysinit.h"
 #include "syscfg/syscfg.h"
 #include "os/os.h"
-#include "os/os_cputime.h"
 #include "stats/stats.h"
 #include "nimble/ble.h"
 #include "nimble/nimble_opt.h"
diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c
index 813db38..caa817e 100644
--- a/nimble/controller/src/ble_ll_adv.c
+++ b/nimble/controller/src/ble_ll_adv.c
@@ -22,7 +22,6 @@
 #include <assert.h>
 #include "syscfg/syscfg.h"
 #include "os/os.h"
-#include "os/os_cputime.h"
 #include "ble/xcvr.h"
 #include "nimble/ble.h"
 #include "nimble/nimble_opt.h"
@@ -37,6 +36,7 @@
 #include "controller/ble_ll_scan.h"
 #include "controller/ble_ll_whitelist.h"
 #include "controller/ble_ll_resolv.h"
+#include "controller/ble_ll_tmr.h"
 #include "controller/ble_ll_trace.h"
 #include "controller/ble_ll_utils.h"
 #include "controller/ble_ll_rfmgmt.h"
@@ -587,7 +587,7 @@ ble_ll_adv_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
 
     /* AuxPtr */
     if (AUX_CURRENT(advsm)->sch.enqueued) {
-        offset = os_cputime_ticks_to_usecs(AUX_CURRENT(advsm)->start_time - advsm->adv_pdu_start_time);
+        offset = ble_ll_tmr_t2u(AUX_CURRENT(advsm)->start_time - advsm->adv_pdu_start_time);
     } else {
         offset = 0;
     }
@@ -620,11 +620,11 @@ ble_ll_adv_put_syncinfo(struct ble_ll_adv_sm *advsm,
         conn_cnt = connsm->event_cntr;
 
         /* get anchor for conn event that is before periodic_adv_event_start_time */
-        while (CPUTIME_GT(anchor, advsm->periodic_adv_event_start_time)) {
+        while (LL_TMR_GT(anchor, advsm->periodic_adv_event_start_time)) {
             ble_ll_conn_get_anchor(connsm, --conn_cnt, &anchor, &anchor_usecs);
         }
 
-        offset = os_cputime_ticks_to_usecs(advsm->periodic_adv_event_start_time - anchor);
+        offset = ble_ll_tmr_t2u(advsm->periodic_adv_event_start_time - anchor);
         offset -= anchor_usecs;
         offset += advsm->periodic_adv_event_start_time_remainder;
 
@@ -639,12 +639,12 @@ ble_ll_adv_put_syncinfo(struct ble_ll_adv_sm *advsm,
          * happen if advertising event is interleaved with periodic advertising
          * event (when chaining).
          */
-        while (CPUTIME_GT(AUX_CURRENT(advsm)->start_time, anchor)) {
+        while (LL_TMR_GT(AUX_CURRENT(advsm)->start_time, anchor)) {
             anchor += advsm->periodic_adv_itvl_ticks;
             event_cnt_off++;
         }
 
-        offset = os_cputime_ticks_to_usecs(anchor - AUX_CURRENT(advsm)->start_time);
+        offset = ble_ll_tmr_t2u(anchor - AUX_CURRENT(advsm)->start_time);
         offset += advsm->periodic_adv_event_start_time_remainder;
         offset += advsm->periodic_adv_itvl_rem_usec;
     }
@@ -776,10 +776,10 @@ ble_ll_adv_aux_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
              */
             offset = 0;
         } else if (advsm->rx_ble_hdr) {
-            offset = os_cputime_ticks_to_usecs(AUX_NEXT(advsm)->start_time - advsm->rx_ble_hdr->beg_cputime);
+            offset = ble_ll_tmr_t2u(AUX_NEXT(advsm)->start_time - advsm->rx_ble_hdr->beg_cputime);
             offset -= (advsm->rx_ble_hdr->rem_usecs + ble_ll_pdu_tx_time_get(12, advsm->sec_phy) + BLE_LL_IFS);
         } else {
-            offset = os_cputime_ticks_to_usecs(AUX_NEXT(advsm)->start_time - aux->start_time);
+            offset = ble_ll_tmr_t2u(AUX_NEXT(advsm)->start_time - aux->start_time);
         }
 
         ble_ll_adv_put_aux_ptr(AUX_NEXT(advsm)->chan, advsm->sec_phy,
@@ -1226,8 +1226,7 @@ ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm)
 
     sch->start_time = advsm->adv_pdu_start_time - g_ble_ll_sched_offset_ticks;
     sch->remainder = 0;
-    sch->end_time = advsm->adv_pdu_start_time +
-                    ble_ll_usecs_to_ticks_round_up(max_usecs);
+    sch->end_time = advsm->adv_pdu_start_time + ble_ll_tmr_u2t_up(max_usecs);
 }
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
@@ -1520,13 +1519,13 @@ ble_ll_adv_aux_schedule_next(struct ble_ll_adv_sm *advsm)
     max_usecs = ble_ll_pdu_tx_time_get(aux_next->payload_len, advsm->sec_phy);
 
     aux_next->start_time = aux->sch.end_time +
-                           ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS + MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY));
+                           ble_ll_tmr_u2t_up(BLE_LL_MAFS +
+                                             MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY));
 
     sch = &aux_next->sch;
     sch->start_time = aux_next->start_time - g_ble_ll_sched_offset_ticks;
     sch->remainder = 0;
-    sch->end_time = aux_next->start_time +
-                    ble_ll_usecs_to_ticks_round_up(max_usecs);
+    sch->end_time = aux_next->start_time + ble_ll_tmr_u2t_up(max_usecs);
     ble_ll_sched_adv_new(&aux_next->sch, ble_ll_adv_aux_scheduled, aux_next);
 
     /*
@@ -1535,7 +1534,7 @@ ble_ll_adv_aux_schedule_next(struct ble_ll_adv_sm *advsm)
      * so advertising will stop after current aux.
      */
     if (advsm->duration &&
-        CPUTIME_GT(aux_next->sch.end_time, advsm->adv_end_time)) {
+        LL_TMR_GT(aux_next->sch.end_time, advsm->adv_end_time)) {
         ble_ll_sched_rmv_elem(&aux_next->sch);
     }
 }
@@ -1595,7 +1594,7 @@ ble_ll_adv_aux_schedule_first(struct ble_ll_adv_sm *advsm)
     sch = &aux->sch;
     sch->start_time = aux->start_time - g_ble_ll_sched_offset_ticks;
     sch->remainder = 0;
-    sch->end_time = aux->start_time + ble_ll_usecs_to_ticks_round_up(max_usecs);
+    sch->end_time = aux->start_time + ble_ll_tmr_u2t_up(max_usecs);
     ble_ll_sched_adv_new(sch, ble_ll_adv_aux_scheduled, aux);
 }
 
@@ -1641,7 +1640,8 @@ ble_ll_adv_aux_set_start_time(struct ble_ll_adv_sm *advsm)
     adv_event_dur = (adv_pdu_dur * chans) + (9 * (chans - 1));
 
     advsm->aux[0].start_time = advsm->adv_event_start_time + adv_event_dur +
-                               ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS + MYNEWT_VAL(BLE_LL_SCHED_AUX_MAFS_DELAY));
+                               ble_ll_tmr_u2t_up(BLE_LL_MAFS +
+                                                 MYNEWT_VAL(BLE_LL_SCHED_AUX_MAFS_DELAY));
 }
 
 static void
@@ -1665,7 +1665,7 @@ ble_ll_adv_aux_schedule(struct ble_ll_adv_sm *advsm)
      * not start extended advertising event which we cannot finish in time.
      */
     if (advsm->duration &&
-        CPUTIME_GT(AUX_CURRENT(advsm)->sch.end_time, advsm->adv_end_time)) {
+        LL_TMR_GT(AUX_CURRENT(advsm)->sch.end_time, advsm->adv_end_time)) {
         ble_ll_adv_sm_stop_timeout(advsm);
     }
 }
@@ -2031,14 +2031,14 @@ ble_ll_adv_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start, void *arg)
      */
     if (advsm->duration) {
         advsm->adv_end_time = advsm->adv_event_start_time +
-                             os_cputime_usecs_to_ticks(advsm->duration * 10000);
+                             ble_ll_tmr_u2t(advsm->duration * 10000);
     }
 #else
     /* Set the time at which we must end directed, high-duty cycle advertising.
      */
     if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
         advsm->adv_end_time = advsm->adv_event_start_time +
-                     os_cputime_usecs_to_ticks(BLE_LL_ADV_STATE_HD_MAX * 1000);
+                     ble_ll_tmr_u2t(BLE_LL_ADV_STATE_HD_MAX * 1000);
     }
 #endif
 }
@@ -2085,7 +2085,8 @@ ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
              */
             offset = 0;
         } else {
-            offset = os_cputime_ticks_to_usecs(SYNC_NEXT(advsm)->start_time - sync->start_time);
+            offset = ble_ll_tmr_t2u(SYNC_NEXT(advsm)->start_time -
+                                    sync->start_time);
         }
 
         ble_ll_adv_put_aux_ptr(SYNC_NEXT(advsm)->chan, advsm->sec_phy,
@@ -2327,15 +2328,13 @@ ble_ll_adv_periodic_schedule_first(struct ble_ll_adv_sm *advsm,
 
     sch = &sync->sch;
 
-    advsm->periodic_adv_event_start_time_remainder += advsm->periodic_adv_itvl_rem_usec;
-    if (advsm->periodic_adv_event_start_time_remainder >= 31) {
-        advsm->periodic_adv_event_start_time++;
-        advsm->periodic_adv_event_start_time_remainder -= 31;
-    }
+    ble_ll_tmr_add_u(&advsm->periodic_adv_event_start_time,
+                     &advsm->periodic_adv_event_start_time_remainder,
+                     advsm->periodic_adv_itvl_rem_usec);
 
     sch->start_time = advsm->periodic_adv_event_start_time;
     sch->remainder = advsm->periodic_adv_event_start_time_remainder;
-    sch->end_time = sch->start_time + ble_ll_usecs_to_ticks_round_up(max_usecs);
+    sch->end_time = sch->start_time + ble_ll_tmr_u2t_up(max_usecs);
     sch->start_time -= g_ble_ll_sched_offset_ticks;
 
     rc = ble_ll_sched_periodic_adv(sch, first_pdu);
@@ -2415,22 +2414,22 @@ ble_ll_adv_periodic_schedule_next(struct ble_ll_adv_sm *advsm)
     max_usecs = ble_ll_pdu_tx_time_get(sync_next->payload_len, advsm->sec_phy);
 
     sync_next->start_time = sync->sch.end_time +
-                            ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS + MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY));
+                            ble_ll_tmr_u2t_up(BLE_LL_MAFS +
+                                              MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY));
 
     sch = &sync_next->sch;
     sch->start_time = sync_next->start_time - g_ble_ll_sched_offset_ticks;
 
     /* adjust for previous packets remainder */
     sch->remainder = sync->sch.remainder;
-    sch->end_time = sync_next->start_time +
-                    ble_ll_usecs_to_ticks_round_up(max_usecs);
+    sch->end_time = sync_next->start_time + ble_ll_tmr_u2t_up(max_usecs);
 
     /* here we can use ble_ll_sched_adv_new as we don't care about timing */
     ble_ll_sched_adv_new(&sync_next->sch, ble_ll_adv_sync_next_scheduled,
                          sync_next);
 
     /* if we are pass advertising interval, drop chain */
-    if (CPUTIME_GT(sch->end_time, advsm->periodic_adv_event_start_time +
+    if (LL_TMR_GT(sch->end_time, advsm->periodic_adv_event_start_time +
                                   advsm->periodic_adv_itvl_ticks)) {
         STATS_INC(ble_ll_stats, periodic_chain_drop_event);
         ble_ll_sched_rmv_elem(&sync->sch);
@@ -2532,7 +2531,6 @@ static void
 ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm)
 {
     uint32_t usecs;
-    uint32_t ticks;
 
     /*
      * The Advertising DID is not required to change when a SyncInfo field is
@@ -2560,21 +2558,16 @@ ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm)
     advsm->periodic_crcinit = ble_ll_rand() & 0xffffff;
 
     usecs = (uint32_t)advsm->periodic_adv_itvl_max * BLE_LL_ADV_PERIODIC_ITVL;
-    ticks = os_cputime_usecs_to_ticks(usecs);
 
-    advsm->periodic_adv_itvl_rem_usec = (usecs - os_cputime_ticks_to_usecs(ticks));
-    if (advsm->periodic_adv_itvl_rem_usec == 31) {
-        advsm->periodic_adv_itvl_rem_usec = 0;
-        ticks++;
-    }
-    advsm->periodic_adv_itvl_ticks = ticks;
+    advsm->periodic_adv_itvl_ticks = ble_ll_tmr_u2t_r(usecs,
+                                                      &advsm->periodic_adv_itvl_rem_usec);
 
     /* There is no point in starting periodic advertising until next advertising
      * event since SyncInfo is needed for synchronization
      */
     advsm->periodic_adv_event_start_time_remainder = 0;
     advsm->periodic_adv_event_start_time = advsm->adv_pdu_start_time +
-                      os_cputime_usecs_to_ticks(advsm->adv_itvl_usecs + 5000);
+                      ble_ll_tmr_u2t(advsm->adv_itvl_usecs + 5000);
 
     ble_ll_adv_sync_schedule(advsm, true);
 }
@@ -2747,8 +2740,8 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
     earliest_start_time = ble_ll_rfmgmt_enable_now();
 
     start_delay_us = ble_ll_rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000);
-    advsm->adv_pdu_start_time = os_cputime_get32() +
-                                os_cputime_usecs_to_ticks(start_delay_us);
+    advsm->adv_pdu_start_time = ble_ll_tmr_get() +
+                                ble_ll_tmr_u2t(start_delay_us);
 
     ble_ll_adv_set_sched(advsm);
 
@@ -3760,8 +3753,8 @@ ble_ll_adv_periodic_check_data_itvl(uint16_t payload_len, uint16_t props,
         pdu_len = ble_ll_adv_sync_get_pdu_len(payload_len, &offset, props);
 
         max_usecs += ble_ll_pdu_tx_time_get(pdu_len, phy);
-        max_usecs += ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS +
-                                MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY));
+        max_usecs += ble_ll_tmr_u2t_up(BLE_LL_MAFS +
+                                       MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY));
     }
 
     itvl_usecs = (uint32_t)itvl * BLE_LL_ADV_PERIODIC_ITVL;
@@ -4630,8 +4623,7 @@ ble_ll_adv_reschedule_event(struct ble_ll_adv_sm *advsm)
         if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
             max_delay_ticks = 0;
         } else {
-            max_delay_ticks =
-                    os_cputime_usecs_to_ticks(BLE_LL_ADV_DELAY_MS_MAX * 1000);
+            max_delay_ticks = ble_ll_tmr_u2t(BLE_LL_ADV_DELAY_MS_MAX * 1000);
         }
 
         rc = ble_ll_sched_adv_reschedule(sch, max_delay_ticks);
@@ -4718,7 +4710,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
          * add the random advDelay as the scheduling code will do that.
          */
         itvl = advsm->adv_itvl_usecs;
-        tick_itvl = os_cputime_usecs_to_ticks(itvl);
+        tick_itvl = ble_ll_tmr_u2t(itvl);
         advsm->adv_event_start_time += tick_itvl;
         advsm->adv_pdu_start_time = advsm->adv_event_start_time;
 
@@ -4728,7 +4720,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
          */
         start_time = advsm->adv_pdu_start_time - g_ble_ll_sched_offset_ticks;
 
-        delta_t = (int32_t)(start_time - os_cputime_get32());
+        delta_t = (int32_t)(start_time - ble_ll_tmr_get());
         if (delta_t < 0) {
             /*
              * NOTE: we just the same interval that we calculated earlier.
@@ -4757,14 +4749,14 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
          * We will transmit right away. Set next pdu start time to now
          * plus a xcvr start delay just so we dont count late adv starts
          */
-        advsm->adv_pdu_start_time = os_cputime_get32() +
+        advsm->adv_pdu_start_time = ble_ll_tmr_get() +
                                     g_ble_ll_sched_offset_ticks;
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
         /* If we're past aux (unlikely, but can happen), just drop an event */
         if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) &&
                 advsm->aux_active &&
-                CPUTIME_GT(advsm->adv_pdu_start_time,
+                LL_TMR_GT(advsm->adv_pdu_start_time,
                            AUX_CURRENT(advsm)->start_time)) {
             ble_ll_adv_drop_event(advsm);
             return;
@@ -4777,7 +4769,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
     /* check if advertising timed out */
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     if (advsm->duration &&
-        CPUTIME_GEQ(advsm->adv_pdu_start_time, advsm->adv_end_time)) {
+        LL_TMR_GEQ(advsm->adv_pdu_start_time, advsm->adv_end_time)) {
         /* Legacy PDUs need to be stop here.
          * For ext adv it will be stopped when AUX is done (unless it was
          * dropped so check if AUX is active here as well).
@@ -4791,7 +4783,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
     }
 #else
     if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) &&
-        CPUTIME_GEQ(advsm->adv_pdu_start_time, advsm->adv_end_time)) {
+        LL_TMR_GEQ(advsm->adv_pdu_start_time, advsm->adv_end_time)) {
         ble_ll_adv_sm_stop_timeout(advsm);
         return;
     }
@@ -4896,7 +4888,7 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm)
 
     /* Check if advertising timed out */
     if (advsm->duration &&
-        CPUTIME_GEQ(advsm->adv_pdu_start_time, advsm->adv_end_time)) {
+        LL_TMR_GEQ(advsm->adv_pdu_start_time, advsm->adv_end_time)) {
         ble_ll_adv_sm_stop_timeout(advsm);
         return;
     }
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index 2fb6586..d3579ed 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -23,7 +23,6 @@
 #include <assert.h>
 #include "syscfg/syscfg.h"
 #include "os/os.h"
-#include "os/os_cputime.h"
 #include "nimble/ble.h"
 #include "nimble/hci_common.h"
 #include "nimble/ble_hci_trans.h"
@@ -37,6 +36,7 @@
 #include "controller/ble_ll_adv.h"
 #include "controller/ble_ll_trace.h"
 #include "controller/ble_ll_rfmgmt.h"
+#include "controller/ble_ll_tmr.h"
 #include "controller/ble_phy.h"
 #include "controller/ble_ll_utils.h"
 #include "ble_ll_conn_priv.h"
@@ -428,19 +428,7 @@ void
 ble_ll_conn_itvl_to_ticks(uint32_t itvl, uint32_t *itvl_ticks,
                           uint8_t *itvl_usecs)
 {
-    uint32_t ticks;
-    uint32_t usecs;
-
-    usecs = itvl * BLE_LL_CONN_ITVL_USECS;
-    ticks = os_cputime_usecs_to_ticks(usecs);
-    usecs = usecs - os_cputime_ticks_to_usecs(ticks);
-    if (usecs == 31) {
-        usecs = 0;
-        ++ticks;
-    }
-
-    *itvl_ticks = ticks;
-    *itvl_usecs = usecs;
+    *itvl_ticks = ble_ll_tmr_u2t_r(itvl * BLE_LL_CONN_ITVL_USECS, itvl_usecs);
 }
 
 /**
@@ -495,7 +483,7 @@ ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2)
     int rc;
 
     /* Set time that we last serviced the schedule */
-    if (CPUTIME_LT(s1->last_scheduled, s2->last_scheduled)) {
+    if (LL_TMR_LT(s1->last_scheduled, s2->last_scheduled)) {
         rc = 1;
     } else {
         rc = 0;
@@ -518,7 +506,7 @@ ble_ll_conn_get_ce_end_time(void)
     if (g_ble_ll_conn_cur_sm) {
         ce_end_time = g_ble_ll_conn_cur_sm->ce_end_time;
     } else {
-        ce_end_time = os_cputime_get32();
+        ce_end_time = ble_ll_tmr_get();
     }
     return ce_end_time;
 }
@@ -779,17 +767,17 @@ ble_ll_conn_get_next_sched_time(struct ble_ll_conn_sm *connsm)
 #else
     uint32_t ce_end;
     uint32_t next_sched_time;
+    uint8_t rem_us;
 
     /* Calculate time at which next connection event will start */
     /* NOTE: We dont care if this time is tick short. */
     ce_end = connsm->anchor_point + connsm->conn_itvl_ticks -
         g_ble_ll_sched_offset_ticks;
-    if ((connsm->anchor_point_usecs + connsm->conn_itvl_usecs) >= 31) {
-        ++ce_end;
-    }
+    rem_us = connsm->anchor_point_usecs;
+    ble_ll_tmr_add_u(&ce_end, &rem_us, connsm->conn_itvl_usecs);
 
     if (ble_ll_sched_next_time(&next_sched_time)) {
-        if (CPUTIME_LT(next_sched_time, ce_end)) {
+        if (LL_TMR_LT(next_sched_time, ce_end)) {
             ce_end = next_sched_time;
         }
     }
@@ -1112,8 +1100,8 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm)
         }
 #endif
 
-        ticks = os_cputime_usecs_to_ticks(ticks);
-        if (CPUTIME_LT(os_cputime_get32() + ticks, next_event_time)) {
+        ticks = ble_ll_tmr_u2t(ticks);
+        if (LL_TMR_LT(ble_ll_tmr_get() + ticks, next_event_time)) {
             md = 1;
         }
     }
@@ -1447,7 +1435,7 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
     }
 
     /* Set time that we last serviced the schedule */
-    connsm->last_scheduled = os_cputime_get32();
+    connsm->last_scheduled = ble_ll_tmr_get();
     return rc;
 }
 
@@ -1517,7 +1505,7 @@ ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime,
         usecs += (BLE_LL_IFS * 2) + connsm->eff_max_rx_time;
 
         ticks = (uint32_t)(next_sched_time - begtime);
-        allowed_usecs = os_cputime_ticks_to_usecs(ticks);
+        allowed_usecs = ble_ll_tmr_t2u(ticks);
         if ((usecs + add_usecs) >= allowed_usecs) {
             rc = 0;
         }
@@ -2004,26 +1992,19 @@ void
 ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event,
                        uint32_t *anchor, uint8_t *anchor_usecs)
 {
-    uint32_t ticks;
     uint32_t itvl;
 
     itvl = (connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS);
 
+    *anchor = connsm->anchor_point;
+    *anchor_usecs = connsm->anchor_point_usecs;
+
     if ((int16_t)(conn_event - connsm->event_cntr) < 0) {
         itvl *= connsm->event_cntr - conn_event;
-        ticks = os_cputime_usecs_to_ticks(itvl);
-        *anchor = connsm->anchor_point - ticks;
+        ble_ll_tmr_sub(anchor, anchor_usecs, itvl);
     } else {
         itvl *= conn_event - connsm->event_cntr;
-        ticks = os_cputime_usecs_to_ticks(itvl);
-        *anchor = connsm->anchor_point + ticks;
-    }
-
-    *anchor_usecs = connsm->anchor_point_usecs;
-    *anchor_usecs += (itvl - os_cputime_ticks_to_usecs(ticks));
-    if (*anchor_usecs >= 31) {
-        (*anchor)++;
-        *anchor_usecs -= 31;
+        ble_ll_tmr_add(anchor, anchor_usecs, itvl);
     }
 }
 #endif
@@ -2047,7 +2028,6 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
     uint32_t max_ww;
 #endif
     struct ble_ll_conn_upd_req *upd;
-    uint32_t ticks;
     uint32_t usecs;
 
     /* XXX: deal with connection request procedure here as well */
@@ -2096,15 +2076,11 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
     /* We can use pre-calculated values for one interval if latency is 1. */
     if (latency == 1) {
         connsm->anchor_point += connsm->conn_itvl_ticks;
-        connsm->anchor_point_usecs += connsm->conn_itvl_usecs;
+        ble_ll_tmr_add_u(&connsm->anchor_point, &connsm->anchor_point_usecs,
+                         connsm->conn_itvl_usecs);
     } else {
-        ticks = os_cputime_usecs_to_ticks(itvl);
-        connsm->anchor_point += ticks;
-        connsm->anchor_point_usecs += (itvl - os_cputime_ticks_to_usecs(ticks));
-    }
-    if (connsm->anchor_point_usecs >= 31) {
-        ++connsm->anchor_point;
-        connsm->anchor_point_usecs -= 31;
+        ble_ll_tmr_add(&connsm->anchor_point, &connsm->anchor_point_usecs,
+                       itvl);
     }
 
     /*
@@ -2140,14 +2116,8 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
 
         if (upd->winoffset != 0) {
             usecs = upd->winoffset * BLE_LL_CONN_ITVL_USECS;
-            ticks = os_cputime_usecs_to_ticks(usecs);
-            connsm->anchor_point += ticks;
-            usecs = usecs - os_cputime_ticks_to_usecs(ticks);
-            connsm->anchor_point_usecs += usecs;
-            if (connsm->anchor_point_usecs >= 31) {
-                ++connsm->anchor_point;
-                connsm->anchor_point_usecs -= 31;
-            }
+            ble_ll_tmr_add(&connsm->anchor_point, &connsm->anchor_point_usecs,
+                           usecs);
         }
 
         /* Reset the starting point of the connection supervision timeout */
@@ -2266,7 +2236,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
         }
         cur_ww += BLE_LL_JITTER_USECS;
         connsm->slave_cur_window_widening = cur_ww;
-        itvl += os_cputime_usecs_to_ticks(cur_ww + connsm->slave_cur_tx_win_usecs);
+        itvl += ble_ll_tmr_u2t(cur_ww + connsm->slave_cur_tx_win_usecs);
     }
 #endif
     itvl -= g_ble_ll_sched_offset_ticks;
@@ -2298,7 +2268,6 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
     uint8_t *evbuf;
 #endif
 #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL)
-    uint32_t endtime;
     uint32_t usecs;
 #endif
 
@@ -2311,7 +2280,7 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
     connsm->csmflags.cfbit.pkt_rxd = 0;
 
     /* Consider time created the last scheduled time */
-    connsm->last_scheduled = os_cputime_get32();
+    connsm->last_scheduled = ble_ll_tmr_get();
 
     /*
      * Set the last rxd pdu time since this is where we want to start the
@@ -2356,25 +2325,22 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
         }
 
         /* Anchor point is cputime. */
-        endtime = os_cputime_usecs_to_ticks(usecs);
-        connsm->anchor_point = rxhdr->beg_cputime + endtime;
-        connsm->anchor_point_usecs = usecs - os_cputime_ticks_to_usecs(endtime);
-        if (connsm->anchor_point_usecs == 31) {
-            ++connsm->anchor_point;
-            connsm->anchor_point_usecs = 0;
-        }
+        connsm->anchor_point = rxhdr->beg_cputime;
+        connsm->anchor_point_usecs = 0;
+        ble_ll_tmr_add(&connsm->anchor_point, &connsm->anchor_point_usecs,
+                       usecs);
 
         connsm->slave_cur_tx_win_usecs =
             connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS;
 #if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
         connsm->ce_end_time = connsm->anchor_point +
             g_ble_ll_sched_data.sch_ticks_per_period +
-            os_cputime_usecs_to_ticks(connsm->slave_cur_tx_win_usecs) + 1;
+            ble_ll_tmr_u2t(connsm->slave_cur_tx_win_usecs) + 1;
 
 #else
         connsm->ce_end_time = connsm->anchor_point +
             (MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_TICKS_PER_SLOT)
-            + os_cputime_usecs_to_ticks(connsm->slave_cur_tx_win_usecs) + 1;
+            + ble_ll_tmr_u2t(connsm->slave_cur_tx_win_usecs) + 1;
 #endif
         connsm->slave_cur_window_widening = BLE_LL_JITTER_USECS;
 
@@ -2571,7 +2537,7 @@ ble_ll_conn_event_end(struct ble_npl_event *ev)
         ble_err = BLE_ERR_CONN_SPVN_TMO;
     }
     /* XXX: Convert to ticks to usecs calculation instead??? */
-    tmo = os_cputime_usecs_to_ticks(tmo);
+    tmo = ble_ll_tmr_u2t(tmo);
     if ((int32_t)(connsm->anchor_point - connsm->last_rxd_pdu_cputime) >= tmo) {
         ble_ll_conn_end(connsm, ble_err);
         return;
@@ -3264,8 +3230,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
         connsm->cons_rxd_bad_crc = 0;
 
         /* Set last valid received pdu time (resets supervision timer) */
-        connsm->last_rxd_pdu_cputime = begtime +
-                                        os_cputime_usecs_to_ticks(add_usecs);
+        connsm->last_rxd_pdu_cputime = begtime + ble_ll_tmr_u2t(add_usecs);
 
         /*
          * Check for valid LLID before proceeding. We have seen some weird
diff --git a/nimble/controller/src/ble_ll_ctrl.c b/nimble/controller/src/ble_ll_ctrl.c
index 432045e..78cf075 100644
--- a/nimble/controller/src/ble_ll_ctrl.c
+++ b/nimble/controller/src/ble_ll_ctrl.c
@@ -29,6 +29,7 @@
 #include "controller/ble_ll_trace.h"
 #include "controller/ble_hw.h"
 #include "controller/ble_ll_sync.h"
+#include "controller/ble_ll_tmr.h"
 #include "ble_ll_conn_priv.h"
 
 #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL)
@@ -2439,8 +2440,7 @@ ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm)
 
         /* Set terminate "timeout" */
         usecs = connsm->supervision_tmo * BLE_HCI_CONN_SPVN_TMO_UNITS * 1000;
-        connsm->terminate_timeout = os_cputime_get32() +
-            os_cputime_usecs_to_ticks(usecs);
+        connsm->terminate_timeout = ble_ll_tmr_get() + ble_ll_tmr_u2t(usecs);
     }
 }
 
diff --git a/nimble/controller/src/ble_ll_dtm.c b/nimble/controller/src/ble_ll_dtm.c
index 8c91677..2c787da 100644
--- a/nimble/controller/src/ble_ll_dtm.c
+++ b/nimble/controller/src/ble_ll_dtm.c
@@ -29,6 +29,7 @@
 #include "controller/ble_phy.h"
 #include "controller/ble_ll_sched.h"
 #include "controller/ble_ll_rfmgmt.h"
+#include "controller/ble_ll_tmr.h"
 #include "ble_ll_dtm_priv.h"
 
 STATS_SECT_START(ble_ll_dtm_stats)
@@ -153,11 +154,8 @@ ble_ll_dtm_set_next(struct dtm_ctx *ctx)
     struct ble_ll_sched_item *sch = &ctx->sch;
 
     ctx->pdu_start_ticks += ctx->itvl_ticks;
-    ctx->pdu_start_usecs += ctx->itvl_rem_usec;
-    if (ctx->pdu_start_usecs >= 31) {
-       ctx->pdu_start_ticks++;
-       ctx->pdu_start_usecs -= 31;
-    }
+    ble_ll_tmr_add_u(&ctx->pdu_start_ticks, &ctx->pdu_start_usecs,
+                     ctx->itvl_rem_usec);
 
     sch->start_time = ctx->pdu_start_ticks;
     sch->remainder = ctx->pdu_start_usecs;
@@ -278,7 +276,6 @@ ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len,
 {
     uint32_t l;
     uint32_t itvl_usec;
-    uint32_t itvl_ticks;
 
     /* Calculate interval as per spec Bluetooth 5.0 Vol 6. Part F, 4.1.6 */
     l = ble_ll_pdu_tx_time_get(len + BLE_LL_PDU_HDR_LEN, phy_mode);
@@ -290,13 +287,7 @@ ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len,
     }
 #endif
 
-    itvl_ticks = os_cputime_usecs_to_ticks(itvl_usec);
-    ctx->itvl_rem_usec = (itvl_usec - os_cputime_ticks_to_usecs(itvl_ticks));
-    if (ctx->itvl_rem_usec == 31) {
-        ctx->itvl_rem_usec = 0;
-        ++itvl_ticks;
-    }
-    ctx->itvl_ticks = itvl_ticks;
+    ctx->itvl_ticks = ble_ll_tmr_u2t_r(itvl_usec, &ctx->itvl_rem_usec);
 }
 
 static int
@@ -410,7 +401,7 @@ ble_ll_dtm_rx_start(void)
 #endif
 
     OS_ENTER_CRITICAL(sr);
-    rc = ble_phy_rx_set_start_time(os_cputime_get32(), 0);
+    rc = ble_phy_rx_set_start_time(ble_ll_tmr_get(), 0);
     OS_EXIT_CRITICAL(sr);
     if (rc && rc != BLE_PHY_ERR_RX_LATE) {
         return rc;
diff --git a/nimble/controller/src/ble_ll_rfmgmt.c b/nimble/controller/src/ble_ll_rfmgmt.c
index 986645f..f73f6b3 100644
--- a/nimble/controller/src/ble_ll_rfmgmt.c
+++ b/nimble/controller/src/ble_ll_rfmgmt.c
@@ -22,11 +22,11 @@
 #include <assert.h>
 #include <stddef.h>
 #include "syscfg/syscfg.h"
-#include "os/os_cputime.h"
 #include "controller/ble_phy.h"
 #include "controller/ble_ll.h"
 #include "controller/ble_ll_sched.h"
 #include "controller/ble_ll_rfmgmt.h"
+#include "controller/ble_ll_tmr.h"
 #include "ble_ll_priv.h"
 
 #if MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME) > 0
@@ -41,7 +41,7 @@ struct ble_ll_rfmgmt_data {
     enum ble_ll_rfmgmt_state state;
     uint16_t ticks_to_enabled;
 
-    struct hal_timer timer;
+    struct ble_ll_tmr timer;
     bool timer_scheduled;
     uint32_t timer_scheduled_at;
 
@@ -64,7 +64,7 @@ ble_ll_rfmgmt_enable(void)
 
     if (g_ble_ll_rfmgmt_data.state == RFMGMT_STATE_OFF) {
         g_ble_ll_rfmgmt_data.state = RFMGMT_STATE_ENABLING;
-        g_ble_ll_rfmgmt_data.enabled_at = os_cputime_get32();
+        g_ble_ll_rfmgmt_data.enabled_at = ble_ll_tmr_get();
         ble_phy_rfclk_enable();
         BLE_LL_DEBUG_GPIO(RFMGMT, 1);
     }
@@ -101,7 +101,7 @@ ble_ll_rfmgmt_timer_reschedule(void)
         enable_at = rfmgmt->enable_sched_at;
     } else {
         rfmgmt->timer_scheduled = false;
-        os_cputime_timer_stop(&rfmgmt->timer);
+        ble_ll_tmr_stop(&rfmgmt->timer);
         return;
     }
 
@@ -118,7 +118,7 @@ ble_ll_rfmgmt_timer_reschedule(void)
         }
 
         rfmgmt->timer_scheduled = false;
-        os_cputime_timer_stop(&rfmgmt->timer);
+        ble_ll_tmr_stop(&rfmgmt->timer);
     }
 
     /*
@@ -128,14 +128,14 @@ ble_ll_rfmgmt_timer_reschedule(void)
      * such case it's absolutely harmless since we already have clock enabled
      * and this will do nothing.
      */
-    if (CPUTIME_LEQ(enable_at, os_cputime_get32())) {
+    if (CPUTIME_LEQ(enable_at, ble_ll_tmr_get())) {
         ble_ll_rfmgmt_enable();
         return;
     }
 
     rfmgmt->timer_scheduled = true;
     rfmgmt->timer_scheduled_at = enable_at;
-    os_cputime_timer_start(&rfmgmt->timer, enable_at);
+    ble_ll_tmr_start(&rfmgmt->timer, enable_at);
 }
 
 static void
@@ -156,7 +156,7 @@ ble_ll_rfmgmt_release_ev(struct ble_npl_event *ev)
 
     OS_ENTER_CRITICAL(sr);
 
-    now = os_cputime_get32();
+    now = ble_ll_tmr_get();
 
     can_disable = true;
     lls = ble_ll_state_get();
@@ -191,7 +191,7 @@ ble_ll_rfmgmt_ticks_to_enabled(void)
         rem_ticks = rfmgmt->ticks_to_enabled;
         break;
     case RFMGMT_STATE_ENABLING:
-        now = os_cputime_get32();
+        now = ble_ll_tmr_get();
         if (CPUTIME_LT(now, rfmgmt->enabled_at + rfmgmt->ticks_to_enabled)) {
             rem_ticks = rfmgmt->enabled_at + rfmgmt->ticks_to_enabled - now;
             break;
@@ -220,10 +220,10 @@ ble_ll_rfmgmt_init(void)
     rfmgmt->state = RFMGMT_STATE_OFF;
 
     rfmgmt->ticks_to_enabled =
-            ble_ll_usecs_to_ticks_round_up(MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME));
+            ble_ll_tmr_u2t_up(MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME));
 
     rfmgmt->timer_scheduled = false;
-    os_cputime_timer_init(&rfmgmt->timer, ble_ll_rfmgmt_timer_exp, NULL);
+    ble_ll_tmr_init(&rfmgmt->timer, ble_ll_rfmgmt_timer_exp, NULL);
 
     ble_npl_event_init(&rfmgmt->release_ev, ble_ll_rfmgmt_release_ev, NULL);
 }
@@ -235,7 +235,7 @@ ble_ll_rfmgmt_reset(void)
 
     rfmgmt->timer_scheduled = false;
     rfmgmt->timer_scheduled_at = 0;
-    os_cputime_timer_stop(&rfmgmt->timer);
+    ble_ll_tmr_stop(&rfmgmt->timer);
 
     ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev);
 
@@ -312,7 +312,7 @@ ble_ll_rfmgmt_enable_now(void)
     ble_ll_rfmgmt_enable();
 
     if (rfmgmt->state == RFMGMT_STATE_ENABLED) {
-        enabled_at = os_cputime_get32();
+        enabled_at = ble_ll_tmr_get();
     } else {
         enabled_at = rfmgmt->enabled_at + rfmgmt->ticks_to_enabled + 1;
     }
diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c
index 987ab46..f96aae6 100644
--- a/nimble/controller/src/ble_ll_scan.c
+++ b/nimble/controller/src/ble_ll_scan.c
@@ -23,7 +23,6 @@
 #include <assert.h>
 #include "syscfg/syscfg.h"
 #include "os/os.h"
-#include "os/os_cputime.h"
 #include "nimble/ble.h"
 #include "nimble/hci_common.h"
 #include "nimble/ble_hci_trans.h"
@@ -35,6 +34,7 @@
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
 #include "controller/ble_ll_scan_aux.h"
 #endif
+#include "controller/ble_ll_tmr.h"
 #include "controller/ble_ll_hci.h"
 #include "controller/ble_ll_whitelist.h"
 #include "controller/ble_ll_resolv.h"
@@ -138,7 +138,7 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm);
 static inline uint32_t
 ble_ll_scan_time_hci_to_ticks(uint16_t value)
 {
-    return os_cputime_usecs_to_ticks(value * BLE_HCI_SCAN_ITVL);
+    return ble_ll_tmr_u2t(value * BLE_HCI_SCAN_ITVL);
 }
 
 /* See Vol 6 Part B Section 4.4.3.2. Active scanning backoff */
@@ -182,7 +182,7 @@ ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm)
     ble_npl_time_t now;
 
     now = ble_npl_time_get();
-    if (CPUTIME_GEQ(now, scansm->scan_nrpa_timer)) {
+    if (LL_TMR_GEQ(now, scansm->scan_nrpa_timer)) {
         /* Generate new NRPA */
         ble_ll_rand_data_get(scansm->scan_nrpa, BLE_DEV_ADDR_LEN);
         scansm->scan_nrpa[5] &= ~0xc0;
@@ -781,7 +781,7 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm)
     ble_phy_mode_set(phy_mode, phy_mode);
 #endif
 
-    rc = ble_phy_rx_set_start_time(os_cputime_get32() +
+    rc = ble_phy_rx_set_start_time(ble_ll_tmr_get() +
                                    g_ble_ll_sched_offset_ticks, 0);
     if (!rc || rc == BLE_PHY_ERR_RX_LATE) {
         /* If we are late here, it is still OK because we keep scanning.
@@ -824,7 +824,7 @@ ble_ll_scan_move_window_to(struct ble_ll_scan_phy *scanp, uint32_t time)
      */
 
     end_time = scanp->timing.start_time + scanp->timing.window;
-    while (CPUTIME_GEQ(time, end_time)) {
+    while (LL_TMR_GEQ(time, end_time)) {
         scanp->timing.start_time += scanp->timing.interval;
         scanp->scan_chan = ble_ll_scan_get_next_adv_prim_chan(scanp->scan_chan);
         end_time = scanp->timing.start_time + scanp->timing.window;
@@ -846,8 +846,8 @@ ble_ll_scan_is_inside_window(struct ble_ll_scan_phy *scanp, uint32_t time)
         return true;
     }
 
-    return CPUTIME_GEQ(time, start_time) &&
-           CPUTIME_LT(time, start_time + scanp->timing.window);
+    return LL_TMR_GEQ(time, start_time) &&
+           LL_TMR_LT(time, start_time + scanp->timing.window);
 }
 
 /**
@@ -862,7 +862,7 @@ ble_ll_scan_sm_stop(int chk_disable)
 
     /* Stop the scanning timer  */
     scansm = &g_ble_ll_scan_sm;
-    os_cputime_timer_stop(&scansm->scan_timer);
+    ble_ll_tmr_stop(&scansm->scan_timer);
 
     /* Only set state if we are currently in a scan window */
     if (chk_disable) {
@@ -965,7 +965,7 @@ ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
     }
 
     /* Start scan at 1st window */
-    os_cputime_timer_start(&scansm->scan_timer, scanp->timing.start_time);
+    ble_ll_tmr_start(&scansm->scan_timer, scanp->timing.start_time);
 
     return BLE_ERR_SUCCESS;
 }
@@ -1025,7 +1025,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
 
     OS_ENTER_CRITICAL(sr);
     if (!scansm->scan_enabled) {
-        os_cputime_timer_stop(&scansm->scan_timer);
+        ble_ll_tmr_stop(&scansm->scan_timer);
         ble_ll_rfmgmt_scan_changed(false, 0);
         ble_ll_rfmgmt_release();
         OS_EXIT_CRITICAL(sr);
@@ -1040,7 +1040,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
         return;
     }
 
-    now = os_cputime_get32();
+    now = ble_ll_tmr_get();
 
     inside_window = ble_ll_scan_is_inside_window(scanp, now);
 
@@ -1054,8 +1054,8 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
          * inside window or has next window earlier than current PHY.
          */
         if (!inside_window &&
-            ((inside_window_next || CPUTIME_LEQ(scanp_next->timing.start_time,
-                                                scanp->timing.start_time)))) {
+            ((inside_window_next || LL_TMR_LEQ(scanp_next->timing.start_time,
+                                               scanp->timing.start_time)))) {
             scansm->scanp = scanp_next;
             scansm->scanp_next = scanp;
             scanp = scansm->scanp;
@@ -1126,7 +1126,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
     }
 
     OS_EXIT_CRITICAL(sr);
-    os_cputime_timer_start(&scansm->scan_timer, next_proc_time);
+    ble_ll_tmr_start(&scansm->scan_timer, next_proc_time);
 }
 
 /**
@@ -1675,7 +1675,7 @@ ble_ll_scan_chk_resume(void)
             return;
         }
 
-        now = os_cputime_get32();
+        now = ble_ll_tmr_get();
         if (ble_ll_state_get() == BLE_LL_STATE_STANDBY &&
             ble_ll_scan_is_inside_window(scansm->scanp, now)) {
             /* Turn on the receiver and set state */
@@ -2643,7 +2643,7 @@ ble_ll_scan_common_init(void)
 #endif
 
     /* Initialize scanning timer */
-    os_cputime_timer_init(&scansm->scan_timer, ble_ll_scan_timer_cb, scansm);
+    ble_ll_tmr_init(&scansm->scan_timer, ble_ll_scan_timer_cb, scansm);
 
     /* Initialize extended scan timers */
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c
index cd60014..94b45e8 100644
--- a/nimble/controller/src/ble_ll_sched.c
+++ b/nimble/controller/src/ble_ll_sched.c
@@ -20,7 +20,6 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <string.h>
-#include "os/os_cputime.h"
 #include "ble/xcvr.h"
 #include "controller/ble_phy.h"
 #include "controller/ble_ll.h"
@@ -30,13 +29,14 @@
 #include "controller/ble_ll_scan_aux.h"
 #include "controller/ble_ll_rfmgmt.h"
 #include "controller/ble_ll_trace.h"
+#include "controller/ble_ll_tmr.h"
 #include "controller/ble_ll_sync.h"
 #include "ble_ll_priv.h"
 #include "ble_ll_conn_priv.h"
 
 #define BLE_LL_SCHED_MAX_DELAY_ANY      (0x7fffffff)
 
-static struct hal_timer g_ble_ll_sched_timer;
+static struct ble_ll_tmr g_ble_ll_sched_timer;
 
 uint8_t g_ble_ll_sched_offset_ticks;
 
@@ -102,8 +102,8 @@ ble_ll_sched_check_overlap(struct ble_ll_sched_item *sch1,
     /* Note: item ranges are defined as [start, end) so items do not overlap
      *       if one item starts at the same time as another ends.
      */
-    return CPUTIME_GT(sch1->end_time, sch2->start_time) &&
-           CPUTIME_GT(sch2->end_time, sch1->start_time);
+    return LL_TMR_GT(sch1->end_time, sch2->start_time) &&
+           LL_TMR_GT(sch2->end_time, sch1->start_time);
 }
 
 static void
@@ -171,7 +171,7 @@ ble_ll_sched_q_head_changed(void)
 
     g_ble_ll_sched_q_head_changed = 1;
 
-    os_cputime_timer_stop(&g_ble_ll_sched_timer);
+    ble_ll_tmr_stop(&g_ble_ll_sched_timer);
 }
 
 static inline void
@@ -190,7 +190,7 @@ ble_ll_sched_restart(void)
     ble_ll_rfmgmt_sched_changed(first);
 
     if (first) {
-        os_cputime_timer_start(&g_ble_ll_sched_timer, first->start_time);
+        ble_ll_tmr_start(&g_ble_ll_sched_timer, first->start_time);
     }
 }
 
@@ -219,7 +219,7 @@ ble_ll_sched_insert(struct ble_ll_sched_item *sch, uint32_t max_delay,
     }
 
     TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
-        if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
+        if (LL_TMR_LEQ(sch->end_time, entry->start_time)) {
             TAILQ_INSERT_BEFORE(entry, sch, link);
             sch->enqueued = 1;
             goto done;
@@ -251,7 +251,7 @@ ble_ll_sched_insert(struct ble_ll_sched_item *sch, uint32_t max_delay,
                  */
                 sch->start_time = entry->end_time + 1;
 
-                if ((max_delay == 0) || CPUTIME_GEQ(sch->start_time,
+                if ((max_delay == 0) || LL_TMR_GEQ(sch->start_time,
                                                     max_start_time)) {
                     sch->enqueued = 0;
                     goto done;
@@ -301,14 +301,14 @@ ble_ll_sched_is_overlap(struct ble_ll_sched_item *s1,
     int rc;
 
     rc = 1;
-    if (CPUTIME_LT(s1->start_time, s2->start_time)) {
+    if (LL_TMR_LT(s1->start_time, s2->start_time)) {
         /* Make sure this event does not overlap current event */
-        if (CPUTIME_LEQ(s1->end_time, s2->start_time)) {
+        if (LL_TMR_LEQ(s1->end_time, s2->start_time)) {
             rc = 0;
         }
     } else {
         /* Check for overlap */
-        if (CPUTIME_GEQ(s1->start_time, s2->end_time)) {
+        if (LL_TMR_GEQ(s1->start_time, s2->end_time)) {
             rc = 0;
         }
     }
@@ -330,7 +330,7 @@ ble_ll_sched_overlaps_current(struct ble_ll_sched_item *sch)
 
     if (ble_ll_state_get() == BLE_LL_STATE_CONNECTION) {
         ce_end_time = ble_ll_conn_get_ce_end_time();
-        if (CPUTIME_GT(ce_end_time, sch->start_time)) {
+        if (LL_TMR_GT(ce_end_time, sch->start_time)) {
             rc = 1;
         }
     }
@@ -377,7 +377,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
 #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL)
     case BLE_LL_CONN_ROLE_SLAVE:
         usecs = connsm->slave_cur_window_widening;
-        sch->start_time -= (os_cputime_usecs_to_ticks(usecs) + 1);
+        sch->start_time -= (ble_ll_tmr_u2t(usecs) + 1);
         sch->remainder = 0;
         break;
 #endif
@@ -389,7 +389,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
     sch->end_time = connsm->ce_end_time;
 
     /* Better be past current time or we just leave */
-    if (CPUTIME_LT(sch->start_time, os_cputime_get32())) {
+    if (LL_TMR_LT(sch->start_time, ble_ll_tmr_get())) {
         return -1;
     }
 
@@ -491,8 +491,8 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
      * wont be listening. We could do better calculation if we wanted to use
      * a transmit window of 1 as opposed to 2, but for now we dont care.
      */
-    dur = os_cputime_usecs_to_ticks(g_ble_ll_sched_data.sch_ticks_per_period);
-    adv_rxend = os_cputime_get32();
+    dur = ble_ll_tmr_u2t(g_ble_ll_sched_data.sch_ticks_per_period);
+    adv_rxend = ble_ll_tmr_get();
     if (ble_hdr->rxinfo.channel >= BLE_PHY_NUM_DATA_CHANS) {
         /*
          * We received packet on advertising channel which means this is a legacy
@@ -584,14 +584,14 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
         rc = 0;
         connsm->tx_win_off = MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET);
     } else {
-        os_cputime_timer_stop(&g_ble_ll_sched_timer);
+        ble_ll_tmr_stop(&g_ble_ll_sched_timer);
         TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
             /* Set these because overlap function needs them to be set */
             sch->start_time = earliest_start;
             sch->end_time = earliest_end;
 
             /* We can insert if before entry in list */
-            if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
+            if (LL_TMR_LEQ(sch->end_time, entry->start_time)) {
                 if ((earliest_start - initial_start) <= itvl_t) {
                     rc = 0;
                     TAILQ_INSERT_BEFORE(entry, sch, link);
@@ -623,7 +623,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
              * the transmit window slightly since the window size is currently
              * 2 when using a 32768 crystal.
              */
-            dur = os_cputime_ticks_to_usecs(earliest_start - initial_start);
+            dur = ble_ll_tmr_t2u(earliest_start - initial_start);
             connsm->tx_win_off = dur / BLE_LL_CONN_TX_OFF_USECS;
         }
     }
@@ -650,7 +650,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
 
     OS_EXIT_CRITICAL(sr);
 
-    os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time);
+    ble_ll_tmr_start(&g_ble_ll_sched_timer, sch->start_time);
 
     return rc;
 }
@@ -712,7 +712,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
      * wont be listening. We could do better calculation if we wanted to use
      * a transmit window of 1 as opposed to 2, but for now we dont care.
      */
-    adv_rxend = os_cputime_get32();
+    adv_rxend = ble_ll_tmr_get();
     if (ble_hdr->rxinfo.channel >= BLE_PHY_NUM_DATA_CHANS) {
         /*
          * We received packet on advertising channel which means this is a legacy
@@ -762,8 +762,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
     rc = ble_ll_sched_insert(sch, max_delay, preempt_none);
 
     if (rc == 0) {
-        connsm->tx_win_off = os_cputime_ticks_to_usecs(sch->start_time -
-                                                       orig_start_time) /
+        connsm->tx_win_off = ble_ll_tmr_t2u(sch->start_time - orig_start_time) /
                              BLE_LL_CONN_TX_OFF_USECS;
 
         connsm->anchor_point = sch->start_time + g_ble_ll_sched_offset_ticks;
@@ -807,7 +806,7 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
      * usecs to ticks could be off by up to 1 tick.
      */
     sch->start_time = connsm->anchor_point - g_ble_ll_sched_offset_ticks -
-        os_cputime_usecs_to_ticks(connsm->slave_cur_window_widening) - 1;
+                      ble_ll_tmr_u2t(connsm->slave_cur_window_widening) - 1;
     sch->end_time = connsm->ce_end_time;
     sch->remainder = 0;
 
@@ -822,22 +821,6 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
     return rc;
 }
 
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-static inline uint32_t
-usecs_to_ticks_fast(uint32_t usecs)
-{
-    uint32_t ticks;
-
-    if (usecs <= 31249) {
-        ticks = (usecs * 137439) / 4194304;
-    } else {
-        ticks = os_cputime_usecs_to_ticks(usecs);
-    }
-
-    return ticks;
-}
-#endif
-
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER)
 /*
  * Determines if the schedule item overlaps the currently running schedule
@@ -863,7 +846,7 @@ ble_ll_sched_sync_overlaps_current(struct ble_ll_sched_item *sch)
         return 0;
     }
 
-    return CPUTIME_GT(end_time, sch->start_time);
+    return LL_TMR_GT(end_time, sch->start_time);
 }
 
 int
@@ -873,31 +856,20 @@ ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch,
                              int8_t phy_mode)
 {
     uint8_t start_time_rem_usecs;
-    uint8_t window_rem_usecs;
-    uint32_t window_ticks;
     uint32_t start_time;
     uint32_t end_time;
     uint32_t dur;
     int rc = 0;
     os_sr_t sr;
 
-    window_ticks = os_cputime_usecs_to_ticks(window_widening);
-    window_rem_usecs = window_widening - os_cputime_ticks_to_usecs(window_ticks);
-
-    /* adjust for subtraction */
-    anchor_point_usecs += 31;
-    anchor_point--;
+    start_time = anchor_point;
+    start_time_rem_usecs = anchor_point_usecs;
 
-    start_time = anchor_point - window_ticks;
-    start_time_rem_usecs = anchor_point_usecs - window_rem_usecs;
-    if (start_time_rem_usecs >= 31) {
-        start_time++;
-        start_time_rem_usecs -= 31;
-    }
+    ble_ll_tmr_sub(&start_time, &start_time_rem_usecs, window_widening);
 
     dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_SYNC_PDU_LEN),
                                  phy_mode);
-    end_time = start_time + os_cputime_usecs_to_ticks(dur);
+    end_time = start_time + ble_ll_tmr_u2t(dur);
 
     start_time -= g_ble_ll_sched_offset_ticks;
 
@@ -907,7 +879,7 @@ ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch,
     sch->end_time = end_time;
 
     /* Better be past current time or we just leave */
-    if (CPUTIME_LEQ(sch->start_time, os_cputime_get32())) {
+    if (LL_TMR_LEQ(sch->start_time, ble_ll_tmr_get())) {
         return -1;
     }
 
@@ -932,28 +904,21 @@ ble_ll_sched_sync(struct ble_ll_sched_item *sch,
                   uint32_t beg_cputime, uint32_t rem_usecs,
                   uint32_t offset, int8_t phy_mode)
 {
-    uint32_t start_time_rem_usecs;
-    uint32_t off_rem_usecs;
+    uint8_t start_time_rem_usecs;
     uint32_t start_time;
-    uint32_t off_ticks;
     uint32_t end_time;
     uint32_t dur;
     os_sr_t sr;
     int rc = 0;
 
-    off_ticks = usecs_to_ticks_fast(offset);
-    off_rem_usecs = offset - os_cputime_ticks_to_usecs(off_ticks);
+    start_time = beg_cputime;
+    start_time_rem_usecs = rem_usecs;
 
-    start_time = beg_cputime + off_ticks;
-    start_time_rem_usecs = rem_usecs + off_rem_usecs;
-    if (start_time_rem_usecs >= 31) {
-        start_time++;
-        start_time_rem_usecs -= 31;
-    }
+    ble_ll_tmr_add(&start_time, &start_time_rem_usecs, offset);
 
     dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_SYNC_PDU_LEN),
                                   phy_mode);
-    end_time = start_time + usecs_to_ticks_fast(dur);
+    end_time = start_time + ble_ll_tmr_u2t(dur);
 
     start_time -= g_ble_ll_sched_offset_ticks;
 
@@ -1042,7 +1007,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch,
     if (rc == 0) {
         next = TAILQ_NEXT(sch, link);
         if (next) {
-            if (CPUTIME_LT(next->start_time, max_end_time)) {
+            if (LL_TMR_LT(next->start_time, max_end_time)) {
                 max_end_time = next->start_time;
             }
             rand_ticks = max_end_time - sch->end_time;
@@ -1198,7 +1163,7 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch)
 
     lls = ble_ll_state_get();
 
-    ble_ll_trace_u32x3(BLE_LL_TRACE_ID_SCHED, lls, os_cputime_get32(),
+    ble_ll_trace_u32x3(BLE_LL_TRACE_ID_SCHED, lls, ble_ll_tmr_get(),
                        sch->start_time);
 
     if (lls == BLE_LL_STATE_STANDBY) {
@@ -1282,7 +1247,7 @@ ble_ll_sched_run(void *arg)
         int32_t dt;
 
         /* Make sure we have passed the start time of the first event */
-        dt = (int32_t)(os_cputime_get32() - sch->start_time);
+        dt = (int32_t)(ble_ll_tmr_get() - sch->start_time);
         if (dt > g_ble_ll_sched_max_late) {
             g_ble_ll_sched_max_late = dt;
         }
@@ -1343,12 +1308,12 @@ ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time,
     int rc;
 
     offset_us += pdu_time_rem;
-    offset_ticks = usecs_to_ticks_fast(offset_us);
+    offset_ticks = ble_ll_tmr_u2t(offset_us);
 
     sch->start_time = pdu_time + offset_ticks - g_ble_ll_sched_offset_ticks;
-    sch->remainder = offset_us - os_cputime_ticks_to_usecs(offset_ticks);
+    sch->remainder = offset_us - ble_ll_tmr_t2u(offset_ticks);
     /* TODO: make some sane slot reservation */
-    sch->end_time = sch->start_time + usecs_to_ticks_fast(5000);
+    sch->end_time = sch->start_time + ble_ll_tmr_u2t(5000);
 
     OS_ENTER_CRITICAL(sr);
 
@@ -1389,7 +1354,7 @@ int ble_ll_sched_dtm(struct ble_ll_sched_item *sch)
 void
 ble_ll_sched_stop(void)
 {
-    os_cputime_timer_stop(&g_ble_ll_sched_timer);
+    ble_ll_tmr_stop(&g_ble_ll_sched_timer);
 }
 
 /**
@@ -1417,16 +1382,15 @@ ble_ll_sched_init(void)
      * This is the offset from the start of the scheduled item until the actual
      * tx/rx should occur, in ticks. We also "round up" to the nearest tick.
      */
-    g_ble_ll_sched_offset_ticks =
-        (uint8_t) os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS + 30);
+    g_ble_ll_sched_offset_ticks = ble_ll_tmr_u2t_up(XCVR_TX_SCHED_DELAY_USECS);
 
     /* Initialize cputimer for the scheduler */
-    os_cputime_timer_init(&g_ble_ll_sched_timer, ble_ll_sched_run, NULL);
+    ble_ll_tmr_init(&g_ble_ll_sched_timer, ble_ll_sched_run, NULL);
 
 #if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
     memset(&g_ble_ll_sched_data, 0, sizeof(struct ble_ll_sched_obj));
     g_ble_ll_sched_data.sch_ticks_per_period =
-        os_cputime_usecs_to_ticks(MYNEWT_VAL(BLE_LL_USECS_PER_PERIOD));
+        ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_USECS_PER_PERIOD));
     g_ble_ll_sched_data.sch_ticks_per_epoch = BLE_LL_SCHED_PERIODS *
         g_ble_ll_sched_data.sch_ticks_per_period;
 #endif
diff --git a/nimble/controller/src/ble_ll_sync.c b/nimble/controller/src/ble_ll_sync.c
index 7b6208c..31e9984 100644
--- a/nimble/controller/src/ble_ll_sync.c
+++ b/nimble/controller/src/ble_ll_sync.c
@@ -32,6 +32,7 @@
 #include "controller/ble_ll_scan.h"
 #include "controller/ble_ll_resolv.h"
 #include "controller/ble_ll_rfmgmt.h"
+#include "controller/ble_ll_tmr.h"
 
 #include "nimble/ble.h"
 #include "nimble/hci_common.h"
@@ -837,7 +838,7 @@ ble_ll_sync_get_event_end_time(void)
     if (g_ble_ll_sync_sm_current) {
         end_time = g_ble_ll_sync_sm_current->sch.end_time;
     } else {
-        end_time = os_cputime_get32();
+        end_time = ble_ll_tmr_get();
     }
     return end_time;
 }
@@ -1138,14 +1139,12 @@ ble_ll_sync_next_event(struct ble_ll_sync_sm *sm, uint32_t cur_ww_adjust)
 {
     uint32_t cur_ww;
     uint32_t max_ww;
-    uint32_t ticks;
     uint32_t itvl;
-    uint8_t usecs;
     uint16_t skip = sm->skip;
 
     /* don't skip if are establishing sync or we missed last event */
     if (skip && ((sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) ||
-                  CPUTIME_LT(sm->last_anchor_point, sm->anchor_point))) {
+                  LL_TMR_LT(sm->last_anchor_point, sm->anchor_point))) {
         skip = 0;
     }
 
@@ -1153,19 +1152,12 @@ ble_ll_sync_next_event(struct ble_ll_sync_sm *sm, uint32_t cur_ww_adjust)
      * interval if not skipping
      */
     if (skip == 0) {
-        ticks = sm->itvl_ticks;
-        usecs = sm->itvl_usecs;
+        sm->anchor_point += sm->itvl_ticks;
+        ble_ll_tmr_add_u(&sm->anchor_point, &sm->anchor_point_usecs,
+                         sm->itvl_usecs);
     } else {
         itvl = sm->itvl * BLE_LL_SYNC_ITVL_USECS * (1 + skip);
-        ticks = os_cputime_usecs_to_ticks(itvl);
-        usecs = itvl - os_cputime_ticks_to_usecs(ticks);
-    }
-
-    sm->anchor_point += ticks;
-    sm->anchor_point_usecs += usecs;
-    if (sm->anchor_point_usecs >= 31) {
-        sm->anchor_point++;
-        sm->anchor_point_usecs -= 31;
+        ble_ll_tmr_add(&sm->anchor_point, &sm->anchor_point_usecs, itvl);
     }
 
     /* Set event counter to the next event */
@@ -1212,7 +1204,7 @@ ble_ll_sync_next_event(struct ble_ll_sync_sm *sm, uint32_t cur_ww_adjust)
      * BLE_LL_SYNC_ESTABLISH_CNT events before failing regardless of timeout
      */
     if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING)) {
-        if (CPUTIME_GT(sm->anchor_point - os_cputime_usecs_to_ticks(cur_ww),
+        if (LL_TMR_GT(sm->anchor_point - ble_ll_tmr_u2t(cur_ww),
                        sm->last_anchor_point + sm->timeout )) {
             return -1;
         }
@@ -1378,13 +1370,7 @@ ble_ll_sync_info_event(struct ble_ll_scan_addr_data *addrd,
 
     /* precalculate interval ticks and usecs */
     usecs = sm->itvl * BLE_LL_SYNC_ITVL_USECS;
-    sm->itvl_ticks = os_cputime_usecs_to_ticks(usecs);
-    sm->itvl_usecs = (uint8_t)(usecs -
-                               os_cputime_ticks_to_usecs(sm->itvl_ticks));
-    if (sm->itvl_usecs == 31) {
-        sm->itvl_usecs = 0;
-        sm->itvl_ticks++;
-    }
+    sm->itvl_ticks = ble_ll_tmr_u2t_r(usecs, &sm->itvl_usecs);
 
     /* Channels Mask (37 bits) */
     sm->chanmap[0] = syncinfo[4];
@@ -1417,7 +1403,7 @@ ble_ll_sync_info_event(struct ble_ll_scan_addr_data *addrd,
     }
 
     /* from now on we only need timeout in ticks */
-    sm->timeout = os_cputime_usecs_to_ticks(sm->timeout);
+    sm->timeout = ble_ll_tmr_u2t(sm->timeout);
 
     sm->phy_mode = rxhdr->rxinfo.phy_mode;
     sm->window_widening = BLE_LL_JITTER_USECS;
@@ -1906,7 +1892,7 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm,
     }
 
     /* set params from transfer */
-    sm->timeout = os_cputime_usecs_to_ticks(sync_timeout);
+    sm->timeout = ble_ll_tmr_u2t(sync_timeout);
     sm->skip = max_skip;
     sm->sync_pending_cnt = BLE_LL_SYNC_ESTABLISH_CNT;
     sm->transfer_id = get_le16(sync_ind); /* first two bytes */
@@ -1936,13 +1922,7 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm,
     sm->itvl = itvl;
 
     /* precalculate interval ticks and usecs */
-    sm->itvl_ticks = os_cputime_usecs_to_ticks(itvl_usecs);
-    sm->itvl_usecs = (uint8_t)(itvl_usecs -
-                               os_cputime_ticks_to_usecs(sm->itvl_ticks));
-    if (sm->itvl_usecs == 31) {
-        sm->itvl_usecs = 0;
-        sm->itvl_ticks++;
-    }
+    sm->itvl_ticks = ble_ll_tmr_u2t_r(itvl_usecs, &sm->itvl_usecs);
 
     /* Channels Mask (37 bits) */
     sm->chanmap[0] = syncinfo[4];
@@ -1997,8 +1977,8 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm,
                                                   sync_anchor, sca);
 
     /* spin until we get anchor in future */
-    future = os_cputime_get32() + g_ble_ll_sched_offset_ticks;
-    while (CPUTIME_LT(sm->anchor_point, future)) {
+    future = ble_ll_tmr_get() + g_ble_ll_sched_offset_ticks;
+    while (LL_TMR_LT(sm->anchor_point, future)) {
         if (ble_ll_sync_next_event(sm, ww_adjust) < 0) {
             /* release SM if this failed */
             ble_ll_sync_transfer_received(sm, BLE_ERR_CONN_ESTABLISHMENT);
@@ -2040,11 +2020,11 @@ ble_ll_sync_put_syncinfo(struct ble_ll_sync_sm *syncsm,
     conn_cnt = connsm->event_cntr;
 
     /* get anchor for conn event that is before periodic_adv_event_start_time */
-    while (CPUTIME_GT(anchor, syncsm->anchor_point)) {
+    while (LL_TMR_GT(anchor, syncsm->anchor_point)) {
         ble_ll_conn_get_anchor(connsm, --conn_cnt, &anchor, &anchor_usecs);
     }
 
-    offset = os_cputime_ticks_to_usecs(syncsm->anchor_point - anchor);
+    offset = ble_ll_tmr_t2u(syncsm->anchor_point - anchor);
     offset -= anchor_usecs;
     offset += syncsm->anchor_point_usecs;
 
diff --git a/nimble/controller/src/ble_ll_utils.c b/nimble/controller/src/ble_ll_utils.c
index ccdf377..e2fe50c 100644
--- a/nimble/controller/src/ble_ll_utils.c
+++ b/nimble/controller/src/ble_ll_utils.c
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include "nimble/ble.h"
 #include "controller/ble_ll.h"
+#include "controller/ble_ll_tmr.h"
 #include "controller/ble_ll_utils.h"
 
 /* 37 bits require 5 bytes */
@@ -291,7 +292,7 @@ ble_ll_utils_calc_window_widening(uint32_t anchor_point,
 
     time_since_last_anchor = (int32_t)(anchor_point - last_anchor_point);
     if (time_since_last_anchor > 0) {
-        delta_msec = os_cputime_ticks_to_usecs(time_since_last_anchor) / 1000;
+        delta_msec = ble_ll_tmr_t2u(time_since_last_anchor) / 1000;
         total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] + MYNEWT_VAL(BLE_LL_SCA);
         window_widening = (total_sca_ppm * delta_msec) / 1000;
     }
diff --git a/nimble/drivers/nrf52/src/ble_phy.c b/nimble/drivers/nrf52/src/ble_phy.c
index 3c7b626..7a12bb5 100644
--- a/nimble/drivers/nrf52/src/ble_phy.c
+++ b/nimble/drivers/nrf52/src/ble_phy.c
@@ -22,6 +22,8 @@
 #include <assert.h>
 #include "syscfg/syscfg.h"
 #include "os/os.h"
+/* Keep os_cputime explicitly to enable build on non-Mynewt platforms */
+#include "os/os_cputime.h"
 #include "ble/xcvr.h"
 #include "nimble/ble.h"
 #include "nimble/nimble_opt.h"