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/16 08:16:12 UTC

[mynewt-nimble] branch master updated (5dda37c -> 32281f2)

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 5dda37c  nimble/transport/uart: Remove unused deps
     new bf31ad0  ble_ll: Add BabbleSim support
     new 9abe36c  babblesim: Add babblesim pkg
     new d81f070  apps/blehci: Add support for BabbleSim
     new 32281f2  travis: Allow ports build to fail

The 4 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:
 .travis.yml                                        |   5 +
 apps/blehci/src/main.c                             |  18 +-
 babblesim/.gitignore                               |   3 +
 babblesim/README.md                                |   1 +
 babblesim/core/include/argparse.h                  |  30 ++
 babblesim/core/include/cmsis.h                     |  51 ++
 babblesim/core/include/core_cm4.h                  |  27 ++
 babblesim/core/include/time_machine.h              |  48 ++
 .../services/bleuart => babblesim/core}/pkg.yml    |  18 +-
 babblesim/core/src/argparse.c                      | 153 ++++++
 babblesim/core/src/cmsis.c                         |  85 ++++
 babblesim/core/src/irq_handler.c                   |  74 +++
 babblesim/core/src/main_config.c                   |  79 ++++
 babblesim/core/src/time_machine.c                  | 255 ++++++++++
 .../cmac_driver => babblesim/hw/babblesim}/pkg.yml |  34 +-
 babblesim/hw/babblesim/scripts/pre_build1.sh       |  69 +++
 babblesim/hw/bsp/nrf52_bsim/bsp.yml                |  60 +++
 babblesim/hw/bsp/nrf52_bsim/include/bsp/bsp.h      |  91 ++++
 .../hw/bsp/nrf52_bsim/include/os/os_arch.h         |  45 +-
 .../hw/bsp/nrf52_bsim/include/os/sim.h             |  56 ++-
 .../hw/bsp/nrf52_bsim/nordic_pca10040_debug.cmd    |  22 +
 .../hw/bsp/nrf52_bsim/nordic_pca10040_debug.sh     |  45 ++
 .../hw/bsp/nrf52_bsim/nordic_pca10040_download.cmd |  22 +
 .../hw/bsp/nrf52_bsim/nordic_pca10040_download.sh  |  40 ++
 .../emspi => babblesim/hw/bsp/nrf52_bsim}/pkg.yml  |  25 +-
 .../hw/bsp/nrf52_bsim/src/arch/bsim_arch/os_arch.c | 110 +++++
 .../src/arch/bsim_arch/os_arch_stack_frame.s       | 104 ++++
 .../bsp/nrf52_bsim/src/arch/bsim_arch/sim_priv.h   |  18 +-
 .../nrf52_bsim/src/arch/bsim_arch/sim_sched_gen.c  | 240 ++++++++++
 .../src/arch/bsim_arch/sim_sched_nosig.c           | 238 ++++++++++
 .../nrf52_bsim/src/arch/bsim_arch/sim_sched_sig.c  | 288 +++++++++++
 .../src/arch/bsim_arch/startup_nrf52_bsim.c        | 231 +++++++++
 babblesim/hw/bsp/nrf52_bsim/src/hal_bsp.c          | 175 +++++++
 babblesim/hw/bsp/nrf52_bsim/src/sbrk.c             |  59 +++
 babblesim/hw/bsp/nrf52_bsim/syscfg.yml             |  73 +++
 .../mcu/nordic/nrf52_bsim/include/mcu/cmsis_nvic.h |  28 ++
 .../mcu/nordic/nrf52_bsim/include/mcu/cortex_m4.h  |  11 +-
 .../hw/mcu/nordic/nrf52_bsim/include/mcu/mcu.h     |  69 +++
 .../hw/mcu/nordic/nrf52_bsim/include/mcu/mcu_sim.h |  17 +-
 .../nordic/nrf52_bsim/include/mcu/nrf52_clock.h    |  26 +-
 .../mcu/nordic/nrf52_bsim/include/mcu/nrf52_hal.h  | 101 ++++
 .../nordic/nrf52_bsim/include/mcu/nrf52_periph.h   |  10 +-
 .../hw/mcu/nordic/nrf52_bsim}/pkg.yml              |  14 +-
 .../hw/mcu/nordic/nrf52_bsim/src/hal_os_tick.c     | 226 +++++++++
 .../hw/mcu/nordic/nrf52_bsim/src/hal_reset_cause.c |  42 +-
 .../hw/mcu/nordic/nrf52_bsim/src/hal_system.c      | 128 +++++
 .../hw/mcu/nordic/nrf52_bsim}/src/hal_timer.c      | 189 ++++----
 babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_uart.c  | 478 +++++++++++++++++++
 .../hw/mcu/nordic/nrf52_bsim/src/hal_watchdog.c    |  16 +-
 .../hw/mcu/nordic/nrf52_bsim/src/native_uart_cfg.c | 248 ++++++++++
 .../nordic/nrf52_bsim/src/native_uart_cfg_priv.h   |  18 +-
 .../hw/mcu/nordic/nrf52_bsim/src/nrf52_clock.c     | 103 ++++
 .../hw/mcu/nordic/nrf52_bsim/src/system_nrf52.c    |  37 ++
 babblesim/hw/mcu/nordic/nrf52_bsim/syscfg.yml      | 526 +++++++++++++++++++++
 babblesim/libc/LICENSE                             | 133 ++++++
 {nimble/host/util => babblesim/libc}/pkg.yml       |  11 +-
 babblesim/libc/src/strlcat.c                       |  30 ++
 babblesim/libc/src/strlcpy.c                       |  26 +
 .../plna/sky66112 => babblesim/nrfx}/pkg.yml       |  22 +-
 .../nrfx/scripts/link_nrfx.sh                      |   7 +-
 nimble/controller/src/ble_ll.c                     |   4 +
 nimble/controller/src/ble_ll_rand.c                |   7 +
 nimble/drivers/nrf52/src/ble_hw.c                  |  24 +-
 nimble/drivers/nrf52/src/ble_phy.c                 | 243 ++++++----
 64 files changed, 5327 insertions(+), 359 deletions(-)
 create mode 100644 babblesim/.gitignore
 create mode 100644 babblesim/README.md
 create mode 100644 babblesim/core/include/argparse.h
 create mode 100644 babblesim/core/include/cmsis.h
 create mode 100644 babblesim/core/include/core_cm4.h
 create mode 100644 babblesim/core/include/time_machine.h
 copy {nimble/host/services/bleuart => babblesim/core}/pkg.yml (76%)
 create mode 100644 babblesim/core/src/argparse.c
 create mode 100644 babblesim/core/src/cmsis.c
 create mode 100644 babblesim/core/src/irq_handler.c
 create mode 100644 babblesim/core/src/main_config.c
 create mode 100644 babblesim/core/src/time_machine.c
 copy {nimble/transport/dialog_cmac/cmac_driver => babblesim/hw/babblesim}/pkg.yml (62%)
 create mode 100755 babblesim/hw/babblesim/scripts/pre_build1.sh
 create mode 100644 babblesim/hw/bsp/nrf52_bsim/bsp.yml
 create mode 100644 babblesim/hw/bsp/nrf52_bsim/include/bsp/bsp.h
 copy nimble/controller/include/controller/ble_ll_plna.h => babblesim/hw/bsp/nrf52_bsim/include/os/os_arch.h (56%)
 copy apps/blestress/src/stress_gatt.h => babblesim/hw/bsp/nrf52_bsim/include/os/sim.h (52%)
 create mode 100755 babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_debug.cmd
 create mode 100755 babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_debug.sh
 create mode 100755 babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_download.cmd
 create mode 100755 babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_download.sh
 copy {nimble/transport/emspi => babblesim/hw/bsp/nrf52_bsim}/pkg.yml (71%)
 create mode 100644 babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/os_arch.c
 create mode 100644 babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/os_arch_stack_frame.s
 copy nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h => babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_priv.h (74%)
 create mode 100644 babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_sched_gen.c
 create mode 100644 babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_sched_nosig.c
 create mode 100644 babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_sched_sig.c
 create mode 100644 babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/startup_nrf52_bsim.c
 create mode 100644 babblesim/hw/bsp/nrf52_bsim/src/hal_bsp.c
 create mode 100644 babblesim/hw/bsp/nrf52_bsim/src/sbrk.c
 create mode 100644 babblesim/hw/bsp/nrf52_bsim/syscfg.yml
 create mode 100644 babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/cmsis_nvic.h
 copy nimble/controller/include/controller/ble_ll_test.h => babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/cortex_m4.h (86%)
 create mode 100644 babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/mcu.h
 copy nimble/controller/src/ble_ll_ctrl_priv.h => babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/mcu_sim.h (76%)
 copy nimble/host/services/ipss/include/services/ipss/ble_svc_ipss.h => babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/nrf52_clock.h (59%)
 create mode 100644 babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/nrf52_hal.h
 copy nimble/transport/uart/include/transport/uart/ble_hci_uart.h => babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/nrf52_periph.h (87%)
 copy {nimble/drivers/nrf52 => babblesim/hw/mcu/nordic/nrf52_bsim}/pkg.yml (83%)
 create mode 100644 babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_os_tick.c
 copy nimble/host/src/ble_hs_log.c => babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_reset_cause.c (53%)
 create mode 100644 babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_system.c
 copy {porting/nimble => babblesim/hw/mcu/nordic/nrf52_bsim}/src/hal_timer.c (85%)
 create mode 100644 babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_uart.c
 copy porting/targets/dummy_app/src/dummy.c => babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_watchdog.c (83%)
 create mode 100644 babblesim/hw/mcu/nordic/nrf52_bsim/src/native_uart_cfg.c
 copy apps/blemesh_models_example_2/src/common.h => babblesim/hw/mcu/nordic/nrf52_bsim/src/native_uart_cfg_priv.h (70%)
 create mode 100644 babblesim/hw/mcu/nordic/nrf52_bsim/src/nrf52_clock.c
 create mode 100644 babblesim/hw/mcu/nordic/nrf52_bsim/src/system_nrf52.c
 create mode 100644 babblesim/hw/mcu/nordic/nrf52_bsim/syscfg.yml
 create mode 100644 babblesim/libc/LICENSE
 copy {nimble/host/util => babblesim/libc}/pkg.yml (82%)
 create mode 100644 babblesim/libc/src/strlcat.c
 create mode 100644 babblesim/libc/src/strlcpy.c
 copy {nimble/drivers/plna/sky66112 => babblesim/nrfx}/pkg.yml (76%)
 copy nimble/host/util/syscfg.yml => babblesim/nrfx/scripts/link_nrfx.sh (87%)
 mode change 100644 => 100755

[mynewt-nimble] 01/04: ble_ll: Add BabbleSim support

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 bf31ad05b7e560821a2a8764842b06e080a54614
Author: Magdalena Kasenberg <ma...@codecoup.pl>
AuthorDate: Tue Nov 2 15:36:10 2021 +0100

    ble_ll: Add BabbleSim support
    
    Co-authored-by: Jakub Rotkiewicz <ja...@codecoup.pl>
---
 nimble/controller/src/ble_ll.c      |   4 +
 nimble/controller/src/ble_ll_rand.c |   7 ++
 nimble/drivers/nrf52/src/ble_hw.c   |  24 ++--
 nimble/drivers/nrf52/src/ble_phy.c  | 243 +++++++++++++++++++++++-------------
 4 files changed, 182 insertions(+), 96 deletions(-)

diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c
index ec40925..5d3cb63 100644
--- a/nimble/controller/src/ble_ll.c
+++ b/nimble/controller/src/ble_ll.c
@@ -358,12 +358,16 @@ static void ble_ll_event_dbuf_overflow(struct ble_npl_event *ev);
 
 #if MYNEWT
 
+#if BABBLESIM
+#define BLE_LL_STACK_SIZE   (4000)
+#else
 /* The BLE LL task data structure */
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
 #define BLE_LL_STACK_SIZE   (120)
 #else
 #define BLE_LL_STACK_SIZE   (90)
 #endif
+#endif
 
 struct os_task g_ble_ll_task;
 
diff --git a/nimble/controller/src/ble_ll_rand.c b/nimble/controller/src/ble_ll_rand.c
index 8aa7127..06e5d12 100644
--- a/nimble/controller/src/ble_ll_rand.c
+++ b/nimble/controller/src/ble_ll_rand.c
@@ -33,6 +33,10 @@
 #include "trng/trng.h"
 #endif
 
+#if BABBLESIM
+extern void tm_tick(void);
+#endif
+
 #if MYNEWT_VAL(TRNG)
 static struct trng_dev *g_trng;
 #else
@@ -116,6 +120,9 @@ ble_ll_rand_data_get(uint8_t *buf, uint8_t len)
             while ((g_ble_ll_rnum_data.rnd_size < len) &&
                    (g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE))) {
                 /* Spin here */
+#if BABBLESIM
+                tm_tick();
+#endif
             }
         }
     }
diff --git a/nimble/drivers/nrf52/src/ble_hw.c b/nimble/drivers/nrf52/src/ble_hw.c
index 79a7772..ef4c28b 100644
--- a/nimble/drivers/nrf52/src/ble_hw.c
+++ b/nimble/drivers/nrf52/src/ble_hw.c
@@ -34,6 +34,8 @@
 #include <nimble/nimble_npl_os.h>
 #endif
 #include "os/os_trace_api.h"
+#include <hal/nrf_rng.h>
+#include "hal/nrf_ecb.h"
 
 /* Total number of resolving list elements */
 #define BLE_HW_RESOLV_LIST_SIZE     (16)
@@ -44,6 +46,10 @@ static uint8_t g_ble_hw_whitelist_mask;
 /* Random number generator isr callback */
 ble_rng_isr_cb_t g_ble_rng_isr_cb;
 
+#if BABBLESIM
+extern void tm_tick(void);
+#endif
+
 /* If LL privacy is enabled, allocate memory for AAR */
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
 
@@ -263,14 +269,14 @@ ble_hw_encrypt_block(struct ble_encryption_block *ecb)
     uint32_t err;
 
     /* Stop ECB */
-    NRF_ECB->TASKS_STOPECB = 1;
+    nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STOPECB);
     /* XXX: does task stop clear these counters? Anyway to do this quicker? */
     NRF_ECB->EVENTS_ENDECB = 0;
     NRF_ECB->EVENTS_ERRORECB = 0;
     NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
 
     /* Start ECB */
-    NRF_ECB->TASKS_STARTECB = 1;
+    nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB);
 
     /* Wait till error or done */
     rc = 0;
@@ -283,6 +289,9 @@ ble_hw_encrypt_block(struct ble_encryption_block *ecb)
             }
             break;
         }
+#if BABBLESIM
+        tm_tick();
+#endif
     }
 
     return rc;
@@ -300,7 +309,7 @@ ble_rng_isr(void)
 
     /* No callback? Clear and disable interrupts */
     if (g_ble_rng_isr_cb == NULL) {
-        NRF_RNG->INTENCLR = 1;
+        nrf_rng_int_disable(NRF_RNG, NRF_RNG_INT_VALRDY_MASK);
         NRF_RNG->EVENTS_VALRDY = 0;
         (void)NRF_RNG->SHORTS;
         os_trace_isr_exit();
@@ -365,10 +374,11 @@ ble_hw_rng_start(void)
     /* No need for interrupt if there is no callback */
     OS_ENTER_CRITICAL(sr);
     NRF_RNG->EVENTS_VALRDY = 0;
+
     if (g_ble_rng_isr_cb) {
-        NRF_RNG->INTENSET = 1;
+        nrf_rng_int_enable(NRF_RNG, NRF_RNG_INT_VALRDY_MASK);
     }
-    NRF_RNG->TASKS_START = 1;
+    nrf_rng_task_trigger(NRF_RNG, NRF_RNG_TASK_START);
     OS_EXIT_CRITICAL(sr);
 
     return 0;
@@ -386,8 +396,8 @@ ble_hw_rng_stop(void)
 
     /* No need for interrupt if there is no callback */
     OS_ENTER_CRITICAL(sr);
-    NRF_RNG->INTENCLR = 1;
-    NRF_RNG->TASKS_STOP = 1;
+    nrf_rng_int_disable(NRF_RNG, NRF_RNG_INT_VALRDY_MASK);
+    nrf_rng_task_trigger(NRF_RNG, NRF_RNG_TASK_STOP);
     NRF_RNG->EVENTS_VALRDY = 0;
     OS_EXIT_CRITICAL(sr);
 
diff --git a/nimble/drivers/nrf52/src/ble_phy.c b/nimble/drivers/nrf52/src/ble_phy.c
index 7a12bb5..6752413 100644
--- a/nimble/drivers/nrf52/src/ble_phy.c
+++ b/nimble/drivers/nrf52/src/ble_phy.c
@@ -20,6 +20,12 @@
 #include <stdint.h>
 #include <string.h>
 #include <assert.h>
+#include <hal/nrf_radio.h>
+#include <hal/nrf_ccm.h>
+#include <hal/nrf_aar.h>
+#include <hal/nrf_timer.h>
+#include <hal/nrf_ppi.h>
+#include <hal/nrf_rtc.h>
 #include "syscfg/syscfg.h"
 #include "os/os.h"
 /* Keep os_cputime explicitly to enable build on non-Mynewt platforms */
@@ -47,6 +53,10 @@
 #endif
 #endif
 
+#if BABBLESIM
+extern void tm_tick(void);
+#endif
+
 /*
  * NOTE: This code uses a couple of PPI channels so care should be taken when
  *       using PPI somewhere else.
@@ -165,6 +175,37 @@ static const uint16_t g_ble_phy_mode_pkt_start_off[BLE_PHY_NUM_MODE] = {
 /* Radio ramp-up times in usecs (fast mode) */
 #define BLE_PHY_T_TXENFAST      (XCVR_TX_RADIO_RAMPUP_USECS)
 #define BLE_PHY_T_RXENFAST      (XCVR_RX_RADIO_RAMPUP_USECS)
+
+#if BABBLESIM
+/* delay between EVENTS_READY and start of tx */
+static const uint8_t g_ble_phy_t_txdelay[BLE_PHY_NUM_MODE] = {
+    [BLE_PHY_MODE_1M] = 0,
+    [BLE_PHY_MODE_2M] = 3,
+    [BLE_PHY_MODE_CODED_125KBPS] = 5,
+    [BLE_PHY_MODE_CODED_500KBPS] = 5
+};
+/* delay between EVENTS_END and end of txd packet */
+static const uint8_t g_ble_phy_t_txenddelay[BLE_PHY_NUM_MODE] = {
+    [BLE_PHY_MODE_1M] = 1,
+    [BLE_PHY_MODE_2M] = 3,
+    [BLE_PHY_MODE_CODED_125KBPS] = 9,
+    [BLE_PHY_MODE_CODED_500KBPS] = 3
+};
+/* delay between rxd access address (w/ TERM1 for coded) and EVENTS_ADDRESS */
+static const uint8_t g_ble_phy_t_rxaddrdelay[BLE_PHY_NUM_MODE] = {
+    [BLE_PHY_MODE_1M] = 9,
+    [BLE_PHY_MODE_2M] = 2,
+    [BLE_PHY_MODE_CODED_125KBPS] = 17,
+    [BLE_PHY_MODE_CODED_500KBPS] = 17
+};
+/* delay between end of rxd packet and EVENTS_END */
+static const uint8_t g_ble_phy_t_rxenddelay[BLE_PHY_NUM_MODE] = {
+    [BLE_PHY_MODE_1M] = 9,
+    [BLE_PHY_MODE_2M] = 2,
+    [BLE_PHY_MODE_CODED_125KBPS] = 27,
+    [BLE_PHY_MODE_CODED_500KBPS] = 22
+};
+#else
 /* delay between EVENTS_READY and start of tx */
 static const uint8_t g_ble_phy_t_txdelay[BLE_PHY_NUM_MODE] = {
     [BLE_PHY_MODE_1M] = 4,
@@ -193,6 +234,7 @@ static const uint8_t g_ble_phy_t_rxenddelay[BLE_PHY_NUM_MODE] = {
     [BLE_PHY_MODE_CODED_125KBPS] = 27,
     [BLE_PHY_MODE_CODED_500KBPS] = 22
 };
+#endif
 
 /* Statistics */
 STATS_SECT_START(ble_phy_stats)
@@ -303,6 +345,7 @@ static uint8_t plna_lna_idx;
 
 #endif
 
+#ifndef BABBLESIM
 static void
 ble_phy_apply_errata_102_106_107(void)
 {
@@ -313,6 +356,7 @@ ble_phy_apply_errata_102_106_107(void)
     *(volatile uint32_t *)0x40001774 = ((*(volatile uint32_t *)0x40001774) &
                          0xfffffffe) | 0x01000000;
 }
+#endif
 
 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
 
@@ -527,6 +571,11 @@ ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
         rem_len -= copy_len;
         block_rem_len -= copy_len;
 
+#if BABBLESIM
+        memcpy(dst, src, copy_len);
+        dst += copy_len;
+        src += copy_len;
+#else
         __asm__ volatile (".syntax unified              \n"
                           "   mov  r4, %[len]           \n"
                           "   b    2f                   \n"
@@ -541,6 +590,7 @@ ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
                           :
                           : "r3", "r4", "memory"
                          );
+#endif
 
         if ((rem_len < 4) && (block_rem_len >= rem_len)) {
             break;
@@ -553,6 +603,10 @@ ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
 
     /* Copy remaining bytes, if any, to last mbuf */
     om->om_len += rem_len;
+
+#if BABBLESIM
+    memcpy(dst, src, rem_len);
+#else
     __asm__ volatile (".syntax unified              \n"
                       "   b    2f                   \n"
                       "1: ldrb r3, [%[src], %[len]] \n"
@@ -563,6 +617,7 @@ ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
                       : [dst] "r" (dst), [src] "r" (src)
                       : "r3", "memory"
                      );
+#endif
 
     /* Copy header */
     memcpy(BLE_MBUF_HDR_PTR(rxpdu), &g_ble_phy_data.rxhdr,
@@ -587,6 +642,9 @@ nrf_wait_disabled(void)
             while (NRF_RADIO->STATE == state) {
                 /* If this fails, something is really wrong. Should last
                  * no more than 6 usecs */
+#if BABBLESIM
+                tm_tick();
+#endif
             }
         }
     }
@@ -658,17 +716,17 @@ ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs, bool tx)
     }
 
     /* Clear and set TIMER0 to fire off at proper time */
-    NRF_TIMER0->TASKS_CLEAR = 1;
-    NRF_TIMER0->CC[0] = rem_usecs;
+    nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CLEAR);
+    nrf_timer_cc_set(NRF_TIMER0, 0, rem_usecs);
     NRF_TIMER0->EVENTS_COMPARE[0] = 0;
 
     /* Set RTC compare to start TIMER0 */
     NRF_RTC0->EVENTS_COMPARE[0] = 0;
-    NRF_RTC0->CC[0] = next_cc;
-    NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
+    nrf_rtc_cc_set(NRF_RTC0, 0, next_cc);
+    nrf_rtc_event_enable(NRF_RTC0, RTC_EVTENSET_COMPARE0_Msk);
 
     /* Enable PPI */
-    NRF_PPI->CHENSET = PPI_CHEN_CH31_Msk;
+    nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH31_Msk);
 
     /* Store the cputime at which we set the RTC */
     g_ble_phy_data.phy_start_cputime = cputime;
@@ -688,8 +746,8 @@ ble_phy_set_start_now(void)
      * Set TIMER0 to fire immediately. We can't set CC to 0 as compare will not
      * occur in such case.
      */
-    NRF_TIMER0->TASKS_CLEAR = 1;
-    NRF_TIMER0->CC[0] = 1;
+    nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CLEAR);
+    nrf_timer_cc_set(NRF_TIMER0, 0, 1);
     NRF_TIMER0->EVENTS_COMPARE[0] = 0;
 
     /*
@@ -700,12 +758,11 @@ ble_phy_set_start_now(void)
      */
     now = os_cputime_get32();
     NRF_RTC0->EVENTS_COMPARE[0] = 0;
-    NRF_RTC0->CC[0] = now + 3;
-    NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
+    nrf_rtc_cc_set(NRF_RTC0, 0, now + 3);
+    nrf_rtc_event_enable(NRF_RTC0, RTC_EVTENSET_COMPARE0_Msk);
 
     /* Enable PPI */
-    NRF_PPI->CHENSET = PPI_CHEN_CH31_Msk;
-
+    nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH31_Msk);
     /*
      * Store the cputime at which we set the RTC
      *
@@ -780,11 +837,11 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs)
     end_time += g_ble_phy_t_rxaddrdelay[phy];
 
     /* wfr_secs is the time from rxen until timeout */
-    NRF_TIMER0->CC[3] = end_time;
+    nrf_timer_cc_set(NRF_TIMER0, 3, end_time);
     NRF_TIMER0->EVENTS_COMPARE[3] = 0;
 
     /* Enable wait for response PPI */
-    NRF_PPI->CHENSET = (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk);
+    nrf_ppi_channels_enable(NRF_PPI, (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk));
 
     /*
      * It may happen that if CPU is halted for a brief moment (e.g. during flash
@@ -798,10 +855,10 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs)
      * CC[1] is only used as a reference on RX start, we do not need it here so
      * it can be used to read TIMER0 counter.
      */
-    NRF_TIMER0->TASKS_CAPTURE[1] = 1;
+    nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE1);
     if (NRF_TIMER0->CC[1] > NRF_TIMER0->CC[3]) {
-        NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk;
-        NRF_RADIO->TASKS_DISABLE = 1;
+        nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk);
+        nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
     }
 }
 
@@ -854,8 +911,8 @@ ble_phy_rx_xcvr_setup(void)
         NRF_CCM->SHORTS = 0;
         NRF_CCM->EVENTS_ERROR = 0;
         NRF_CCM->EVENTS_ENDCRYPT = 0;
-        NRF_CCM->TASKS_KSGEN = 1;
-        NRF_PPI->CHENSET = PPI_CHEN_CH25_Msk;
+        nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_KSGEN);
+        nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH25_Msk);
     } else {
         NRF_RADIO->PACKETPTR = (uint32_t)dptr;
     }
@@ -879,7 +936,7 @@ ble_phy_rx_xcvr_setup(void)
 #endif
 
     /* Turn off trigger TXEN on output compare match and AAR on bcmatch */
-    NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk;
+    nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk);
 
     /* Reset the rx started flag. Used for the wait for response */
     g_ble_phy_data.phy_rx_started = 0;
@@ -901,7 +958,7 @@ ble_phy_rx_xcvr_setup(void)
 #endif
 
     /* I want to know when 1st byte received (after address) */
-    NRF_RADIO->BCC = 8 + g_ble_phy_data.phy_bcc_offset; /* in bits */
+    nrf_radio_bcc_set(NRF_RADIO, 8 + g_ble_phy_data.phy_bcc_offset); /* in bits */
     NRF_RADIO->EVENTS_ADDRESS = 0;
     NRF_RADIO->EVENTS_DEVMATCH = 0;
     NRF_RADIO->EVENTS_BCMATCH = 0;
@@ -913,8 +970,8 @@ ble_phy_rx_xcvr_setup(void)
                         RADIO_SHORTS_ADDRESS_RSSISTART_Msk |
                         RADIO_SHORTS_DISABLED_RSSISTOP_Msk;
 
-    NRF_RADIO->INTENSET = RADIO_INTENSET_ADDRESS_Msk |
-                          RADIO_INTENSET_DISABLED_Msk;
+    nrf_radio_int_enable(NRF_RADIO, RADIO_INTENSET_ADDRESS_Msk |
+                         RADIO_INTENSET_DISABLED_Msk);
 }
 
 /**
@@ -978,9 +1035,9 @@ ble_phy_tx_end_isr(void)
         /* Start listening a bit earlier due to allowed active clock accuracy */
         rx_time -= 2;
 
-        NRF_TIMER0->CC[0] = rx_time;
+        nrf_timer_cc_set(NRF_TIMER0, 0, rx_time);
         NRF_TIMER0->EVENTS_COMPARE[0] = 0;
-        NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk;
+        nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk);
 
         ble_phy_plna_enable_lna();
     } else {
@@ -988,10 +1045,10 @@ ble_phy_tx_end_isr(void)
          * XXX: not sure we need to stop the timer here all the time. Or that
          * it should be stopped here.
          */
-        NRF_TIMER0->TASKS_STOP = 1;
+        nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_STOP);
         NRF_TIMER0->TASKS_SHUTDOWN = 1;
-        NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk |
-                           PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk;
+        nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk |
+                                 PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk);
         assert(transition == BLE_PHY_TRANSITION_NONE);
     }
 }
@@ -1031,7 +1088,7 @@ ble_phy_rx_end_isr(void)
     struct ble_mbuf_hdr *ble_hdr;
 
     /* Disable automatic RXEN */
-    NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
+    nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH21_Msk);
 
     /* Set RSSI and CRC status flag in header */
     ble_hdr = &g_ble_phy_data.rxhdr;
@@ -1107,9 +1164,9 @@ ble_phy_rx_end_isr(void)
     /* Adjust for delay between EVENT_READY and actual TX start time */
     tx_time -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode];
 
-    NRF_TIMER0->CC[0] = tx_time;
+    nrf_timer_cc_set(NRF_TIMER0, 0, tx_time);
     NRF_TIMER0->EVENTS_COMPARE[0] = 0;
-    NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk;
+    nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH20_Msk);
 
     ble_phy_plna_enable_pa();
 
@@ -1125,9 +1182,9 @@ ble_phy_rx_end_isr(void)
      *
      * Note: CC[3] is used only for wfr which we do not need here.
      */
-    NRF_TIMER0->TASKS_CAPTURE[3] = 1;
+    nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3);
     if (NRF_TIMER0->CC[3] > NRF_TIMER0->CC[0]) {
-        NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
+        nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk);
         g_ble_phy_data.phy_transition_late = 1;
     }
 
@@ -1162,10 +1219,10 @@ ble_phy_rx_start_isr(void)
 
     /* Clear events and clear interrupt */
     NRF_RADIO->EVENTS_ADDRESS = 0;
-    NRF_RADIO->INTENCLR = RADIO_INTENCLR_ADDRESS_Msk;
+    nrf_radio_int_disable(NRF_RADIO, RADIO_INTENCLR_ADDRESS_Msk);
 
     /* Clear wfr timer channels */
-    NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk;
+    nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk);
 
     /* Initialize the ble mbuf header */
     ble_hdr = &g_ble_phy_data.rxhdr;
@@ -1221,10 +1278,14 @@ ble_phy_rx_start_isr(void)
          * something is wrong!
          */
         if (state == RADIO_STATE_STATE_Disabled) {
-            NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+            nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_IRQ_MASK_ALL);
             NRF_RADIO->SHORTS = 0;
             return false;
         }
+
+#if BABBLESIM
+        tm_tick();
+#endif
     }
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
@@ -1243,9 +1304,9 @@ ble_phy_rx_start_isr(void)
 
         /* Trigger AAR after last bit of AdvA is received */
         NRF_RADIO->EVENTS_BCMATCH = 0;
-        NRF_PPI->CHENSET = PPI_CHEN_CH23_Msk;
-        NRF_RADIO->BCC = (BLE_LL_PDU_HDR_LEN + adva_offset + BLE_DEV_ADDR_LEN) * 8 +
-                         g_ble_phy_data.phy_bcc_offset;
+        nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH23_Msk);
+        nrf_radio_bcc_set(NRF_RADIO, (BLE_LL_PDU_HDR_LEN + adva_offset +
+            BLE_DEV_ADDR_LEN) * 8 + g_ble_phy_data.phy_bcc_offset);
     }
 #endif
 
@@ -1276,7 +1337,7 @@ ble_phy_isr(void)
     os_trace_isr_enter();
 
     /* Read irq register to determine which interrupts are enabled */
-    irq_en = NRF_RADIO->INTENCLR;
+    irq_en = NRF_RADIO->INTENSET;
 
     /*
      * NOTE: order of checking is important! Possible, if things get delayed,
@@ -1311,7 +1372,7 @@ ble_phy_isr(void)
                        !g_ble_phy_data.phy_rx_started));
         NRF_RADIO->EVENTS_END = 0;
         NRF_RADIO->EVENTS_DISABLED = 0;
-        NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk;
+        nrf_radio_int_disable(NRF_RADIO, RADIO_INTENCLR_DISABLED_Msk);
 
         switch (g_ble_phy_data.phy_state) {
         case BLE_PHY_STATE_RX:
@@ -1397,39 +1458,40 @@ ble_phy_dbg_time_setup(void)
 #if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0
     idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN));
 
-    NRF_PPI->CH[17].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY);
-    NRF_PPI->CH[17].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]);
-    NRF_PPI->CHENSET = PPI_CHEN_CH17_Msk;
+    nrf_ppi_channel_endpoint_setup(NRF_PPI, 17, (uint32_t)&(NRF_RADIO->EVENTS_READY),
+                                   (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]));
+    nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH17_Msk);
 
     /* CH[20] and PPI CH[21] are on to trigger TASKS_TXEN or TASKS_RXEN */
-    NRF_PPI->FORK[20].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]);
-    NRF_PPI->FORK[21].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]);
+    nrf_ppi_fork_endpoint_setup(NRF_PPI, 20, (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]));
+    nrf_ppi_fork_endpoint_setup(NRF_PPI, 21, (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]));
 #endif
 
 #if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0
     idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN));
 
     /* CH[26] and CH[27] are always on for EVENT_ADDRESS and EVENT_END */
-    NRF_PPI->FORK[26].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]);
-    NRF_PPI->FORK[27].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]);
+    nrf_ppi_fork_endpoint_setup(NRF_PPI, 26, (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]));
+    nrf_ppi_fork_endpoint_setup(NRF_PPI, 27, (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]));
 #endif
 
 #if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0
     idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN));
 
 #if NRF52840_XXAA
-    NRF_PPI->CH[18].EEP = (uint32_t)&(NRF_RADIO->EVENTS_RXREADY);
+    nrf_ppi_channel_endpoint_setup(NRF_PPI, 18, (uint32_t)&(NRF_RADIO->EVENTS_RXREADY),
+                                   (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]));
 #else
-    NRF_PPI->CH[18].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY);
+    nrf_ppi_channel_endpoint_setup(NRF_PPI, 18, (uint32_t)&(NRF_RADIO->EVENTS_READY),
+                                   (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]));
 #endif
-    NRF_PPI->CH[18].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]);
-    NRF_PPI->CH[19].EEP = (uint32_t)&(NRF_RADIO->EVENTS_DISABLED);
-    NRF_PPI->CH[19].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]);
-    NRF_PPI->CHENSET = PPI_CHEN_CH18_Msk | PPI_CHEN_CH19_Msk;
+    nrf_ppi_channel_endpoint_setup(NRF_PPI, 19, (uint32_t)&(NRF_RADIO->EVENTS_DISABLED),
+                                   (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]));
+    nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH18_Msk | PPI_CHEN_CH19_Msk);
 
     /* CH[4] and CH[5] are always on for wfr */
-    NRF_PPI->FORK[4].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]);
-    NRF_PPI->FORK[5].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]);
+    nrf_ppi_fork_endpoint_setup(NRF_PPI, 4, (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]));
+    nrf_ppi_fork_endpoint_setup(NRF_PPI, 5, (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]));
 #endif
 }
 
@@ -1458,11 +1520,11 @@ ble_phy_init(void)
     g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
 
     /* Toggle peripheral power to reset (just in case) */
-    NRF_RADIO->POWER = 0;
-    NRF_RADIO->POWER = 1;
+    nrf_radio_power_set(NRF_RADIO, false);
+    nrf_radio_power_set(NRF_RADIO, true);
 
     /* Disable all interrupts */
-    NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+    nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_IRQ_MASK_ALL);
 
     /* Set configuration registers */
     NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit;
@@ -1492,10 +1554,10 @@ ble_phy_init(void)
     NRF_RADIO->TIFS = BLE_LL_IFS;
 
     /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */
-    NRF_PPI->CHENSET = PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk;
+    nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk);
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
-    NRF_CCM->INTENCLR = 0xffffffff;
+    nrf_ccm_int_disable(NRF_CCM, 0xffffffff);
     NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk;
     NRF_CCM->EVENTS_ERROR = 0;
     memset(g_nrf_encrypt_scratchpad, 0, sizeof(g_nrf_encrypt_scratchpad));
@@ -1504,7 +1566,7 @@ ble_phy_init(void)
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
     g_ble_phy_data.phy_aar_scratch = 0;
     NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0];
-    NRF_AAR->INTENCLR = 0xffffffff;
+    nrf_aar_int_disable(NRF_AAR, 0xffffffff);
     NRF_AAR->EVENTS_END = 0;
     NRF_AAR->EVENTS_RESOLVED = 0;
     NRF_AAR->EVENTS_NOTRESOLVED = 0;
@@ -1512,7 +1574,7 @@ ble_phy_init(void)
 #endif
 
     /* TIMER0 setup for PHY when using RTC */
-    NRF_TIMER0->TASKS_STOP = 1;
+    nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_STOP);
     NRF_TIMER0->TASKS_SHUTDOWN = 1;
     NRF_TIMER0->BITMODE = 3;    /* 32-bit timer */
     NRF_TIMER0->MODE = 0;       /* Timer mode */
@@ -1525,10 +1587,12 @@ ble_phy_init(void)
      * Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait
      *            for response timer.
      */
-    NRF_PPI->CH[4].EEP = (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS);
-    NRF_PPI->CH[4].TEP = (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3]);
-    NRF_PPI->CH[5].EEP = (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]);
-    NRF_PPI->CH[5].TEP = (uint32_t)&(NRF_RADIO->TASKS_DISABLE);
+    nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL4,
+        (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS),
+        (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3]));
+    nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL5,
+        (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]),
+        (uint32_t)&(NRF_RADIO->TASKS_DISABLE));
 
 #if MYNEWT_VAL(BLE_LL_PA) || MYNEWT_VAL(BLE_LL_LNA)
 #if PLNA_SINGLE_GPIO
@@ -1606,7 +1670,7 @@ ble_phy_rx(void)
     }
 
     /* Make sure all interrupts are disabled */
-    NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+    nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_IRQ_MASK_ALL);
 
     /* Clear events prior to enabling receive */
     NRF_RADIO->EVENTS_END = 0;
@@ -1656,8 +1720,8 @@ ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir)
 void
 ble_phy_encrypt_disable(void)
 {
-    NRF_PPI->CHENCLR = PPI_CHEN_CH25_Msk;
-    NRF_CCM->TASKS_STOP = 1;
+    nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH25_Msk);
+    nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_STOP);
     NRF_CCM->EVENTS_ERROR = 0;
     NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled;
 
@@ -1703,7 +1767,7 @@ ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
 
     /* XXX: This should not be necessary, but paranoia is good! */
     /* Clear timer0 compare to RXEN since we are transmitting */
-    NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
+    nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH21_Msk);
 
     if (ble_phy_set_start_time(cputime, rem_usecs, true) != 0) {
         STATS_INC(ble_phy_stats, tx_late);
@@ -1711,7 +1775,7 @@ ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
         rc = BLE_PHY_ERR_TX_LATE;
     } else {
         /* Enable PPI to automatically start TXEN */
-        NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk;
+        nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH20_Msk);
         rc = 0;
 
         ble_phy_plna_enable_pa();
@@ -1747,7 +1811,7 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
 
     /* XXX: This should not be necessary, but paranoia is good! */
     /* Clear timer0 compare to TXEN since we are transmitting */
-    NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
+    nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk);
 
     if (ble_phy_set_start_time(cputime, rem_usecs, false) != 0) {
         STATS_INC(ble_phy_stats, rx_late);
@@ -1759,7 +1823,7 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
     }
 
     /* Enable PPI to automatically start RXEN */
-    NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk;
+    nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk);
 
     ble_phy_plna_enable_lna();
 
@@ -1807,8 +1871,8 @@ ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)
      * paranoid, and if you are going to clear one, might as well clear them
      * all.
      */
-    NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH23_Msk |
-                       PPI_CHEN_CH25_Msk;
+    nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk |
+                             PPI_CHEN_CH23_Msk | PPI_CHEN_CH25_Msk);
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
     if (g_ble_phy_data.phy_encrypted) {
@@ -1844,7 +1908,7 @@ ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
     /* Start key-stream generation and encryption (via short) */
     if (g_ble_phy_data.phy_encrypted) {
-        NRF_CCM->TASKS_KSGEN = 1;
+        nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_KSGEN);
     }
 #endif
 
@@ -1858,7 +1922,7 @@ ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)
     /* Enable shortcuts for transmit start/end. */
     shortcuts = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk;
     NRF_RADIO->SHORTS = shortcuts;
-    NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
+    nrf_radio_int_enable(NRF_RADIO, RADIO_INTENSET_DISABLED_Msk);
 
     /* Set the PHY transition */
     g_ble_phy_data.phy_transition = end_trans;
@@ -1970,8 +2034,9 @@ ble_phy_set_access_addr(uint32_t access_addr)
 
     g_ble_phy_data.phy_access_address = access_addr;
 
+#ifndef BABBLESIM
     ble_phy_apply_errata_102_106_107();
-
+#endif
     return 0;
 }
 
@@ -2038,9 +2103,9 @@ ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
 static void
 ble_phy_stop_usec_timer(void)
 {
-    NRF_TIMER0->TASKS_STOP = 1;
+    nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_STOP);
     NRF_TIMER0->TASKS_SHUTDOWN = 1;
-    NRF_RTC0->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk;
+    nrf_rtc_event_disable(NRF_RTC0, RTC_EVTENSET_COMPARE0_Msk);
 }
 
 /**
@@ -2054,13 +2119,13 @@ ble_phy_stop_usec_timer(void)
 static void
 ble_phy_disable_irq_and_ppi(void)
 {
-    NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+    nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_IRQ_MASK_ALL);
     NRF_RADIO->SHORTS = 0;
-    NRF_RADIO->TASKS_DISABLE = 1;
-    NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH20_Msk |
-          PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk |
-          PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk;
-    NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk;
+    nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
+    nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk |
+        PPI_CHEN_CH20_Msk | PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk |
+        PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk);
+    nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk);
     NVIC_ClearPendingIRQ(RADIO_IRQn);
     g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
 }
@@ -2073,7 +2138,7 @@ ble_phy_restart_rx(void)
 
     ble_phy_set_start_now();
     /* Enable PPI to automatically start RXEN */
-    NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk;
+    nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk);
 
     ble_phy_rx();
 }
@@ -2185,7 +2250,7 @@ ble_phy_rfclk_enable(void)
 #if MYNEWT
     nrf52_clock_hfxo_request();
 #else
-    NRF_CLOCK->TASKS_HFCLKSTART = 1;
+    nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTART);
 #endif
 }
 
@@ -2195,6 +2260,6 @@ ble_phy_rfclk_disable(void)
 #if MYNEWT
     nrf52_clock_hfxo_release();
 #else
-    NRF_CLOCK->TASKS_HFCLKSTOP = 1;
+    nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTOP);
 #endif
 }

[mynewt-nimble] 04/04: travis: Allow ports build to fail

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 32281f273908e75593e920d1e04e6954f9fe7732
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Tue Feb 15 16:41:06 2022 +0100

    travis: Allow ports build to fail
    
    This is temporary until issues with RIOT are resolved.
---
 .travis.yml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index 185ca35..7567ce3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,6 +35,11 @@ git:
   depth: false
 
 matrix:
+  allow_failures:
+    - env:
+        - TEST=BUILD_PORTS
+        - VM_AMOUNT=1
+        - TARGET_SET=1
   include:
     # Style checking
     - os: linux

[mynewt-nimble] 02/04: babblesim: Add babblesim pkg

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 9abe36cc3c489370deb75fd9c265505fae82c656
Author: Magdalena Kasenberg <ma...@codecoup.pl>
AuthorDate: Thu Nov 25 18:05:43 2021 +0100

    babblesim: Add babblesim pkg
    
    Co-authored-by: Jakub Rotkiewicz <ja...@codecoup.pl>
    Co-authored-by: Andrzej Kaczmarek <an...@codecoup.pl>
---
 babblesim/.gitignore                               |   3 +
 babblesim/README.md                                |   1 +
 babblesim/core/include/argparse.h                  |  30 +
 babblesim/core/include/cmsis.h                     |  51 ++
 babblesim/core/include/core_cm4.h                  |  27 +
 babblesim/core/include/time_machine.h              |  48 ++
 babblesim/core/pkg.yml                             |  37 +
 babblesim/core/src/argparse.c                      | 153 ++++
 babblesim/core/src/cmsis.c                         |  85 ++
 babblesim/core/src/irq_handler.c                   |  74 ++
 babblesim/core/src/main_config.c                   |  79 ++
 babblesim/core/src/time_machine.c                  | 255 ++++++
 babblesim/hw/babblesim/pkg.yml                     |  44 +
 babblesim/hw/babblesim/scripts/pre_build1.sh       |  69 ++
 babblesim/hw/bsp/nrf52_bsim/bsp.yml                |  60 ++
 babblesim/hw/bsp/nrf52_bsim/include/bsp/bsp.h      |  91 ++
 babblesim/hw/bsp/nrf52_bsim/include/os/os_arch.h   |  64 ++
 babblesim/hw/bsp/nrf52_bsim/include/os/sim.h       |  60 ++
 .../hw/bsp/nrf52_bsim/nordic_pca10040_debug.cmd    |  22 +
 .../hw/bsp/nrf52_bsim/nordic_pca10040_debug.sh     |  45 +
 .../hw/bsp/nrf52_bsim/nordic_pca10040_download.cmd |  22 +
 .../hw/bsp/nrf52_bsim/nordic_pca10040_download.sh  |  40 +
 babblesim/hw/bsp/nrf52_bsim/pkg.yml                |  37 +
 .../hw/bsp/nrf52_bsim/src/arch/bsim_arch/os_arch.c | 110 +++
 .../src/arch/bsim_arch/os_arch_stack_frame.s       | 104 +++
 .../bsp/nrf52_bsim/src/arch/bsim_arch/sim_priv.h   |  44 +
 .../nrf52_bsim/src/arch/bsim_arch/sim_sched_gen.c  | 240 ++++++
 .../src/arch/bsim_arch/sim_sched_nosig.c           | 238 ++++++
 .../nrf52_bsim/src/arch/bsim_arch/sim_sched_sig.c  | 288 +++++++
 .../src/arch/bsim_arch/startup_nrf52_bsim.c        | 231 +++++
 babblesim/hw/bsp/nrf52_bsim/src/hal_bsp.c          | 175 ++++
 babblesim/hw/bsp/nrf52_bsim/src/sbrk.c             |  59 ++
 babblesim/hw/bsp/nrf52_bsim/syscfg.yml             |  73 ++
 .../mcu/nordic/nrf52_bsim/include/mcu/cmsis_nvic.h |  28 +
 .../mcu/nordic/nrf52_bsim/include/mcu/cortex_m4.h  |  34 +
 .../hw/mcu/nordic/nrf52_bsim/include/mcu/mcu.h     |  69 ++
 .../hw/mcu/nordic/nrf52_bsim/include/mcu/mcu_sim.h |  38 +
 .../nordic/nrf52_bsim/include/mcu/nrf52_clock.h    |  50 ++
 .../mcu/nordic/nrf52_bsim/include/mcu/nrf52_hal.h  | 101 +++
 .../nordic/nrf52_bsim/include/mcu/nrf52_periph.h   |  33 +
 babblesim/hw/mcu/nordic/nrf52_bsim/pkg.yml         |  29 +
 .../hw/mcu/nordic/nrf52_bsim/src/hal_os_tick.c     | 226 +++++
 .../hw/mcu/nordic/nrf52_bsim/src/hal_reset_cause.c |  47 +
 .../hw/mcu/nordic/nrf52_bsim/src/hal_system.c      | 128 +++
 babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_timer.c | 949 +++++++++++++++++++++
 babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_uart.c  | 478 +++++++++++
 .../hw/mcu/nordic/nrf52_bsim/src/hal_watchdog.c    |  36 +
 .../hw/mcu/nordic/nrf52_bsim/src/native_uart_cfg.c | 248 ++++++
 .../nordic/nrf52_bsim/src/native_uart_cfg_priv.h   |  31 +
 .../hw/mcu/nordic/nrf52_bsim/src/nrf52_clock.c     | 103 +++
 .../hw/mcu/nordic/nrf52_bsim/src/system_nrf52.c    |  37 +
 babblesim/hw/mcu/nordic/nrf52_bsim/syscfg.yml      | 526 ++++++++++++
 babblesim/libc/LICENSE                             | 133 +++
 babblesim/libc/pkg.yml                             |  28 +
 babblesim/libc/src/strlcat.c                       |  30 +
 babblesim/libc/src/strlcpy.c                       |  26 +
 babblesim/nrfx/pkg.yml                             |  37 +
 babblesim/nrfx/scripts/link_nrfx.sh                |  24 +
 58 files changed, 6428 insertions(+)

diff --git a/babblesim/.gitignore b/babblesim/.gitignore
new file mode 100644
index 0000000..78e34f1
--- /dev/null
+++ b/babblesim/.gitignore
@@ -0,0 +1,3 @@
+hw/babblesim/components
+hw/babblesim/src
+nrfx/src
\ No newline at end of file
diff --git a/babblesim/README.md b/babblesim/README.md
new file mode 100644
index 0000000..c9ba3ef
--- /dev/null
+++ b/babblesim/README.md
@@ -0,0 +1 @@
+BabbleSim support for Apache NimBLE
diff --git a/babblesim/core/include/argparse.h b/babblesim/core/include/argparse.h
new file mode 100644
index 0000000..7f98b02
--- /dev/null
+++ b/babblesim/core/include/argparse.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017 Oticon A/S
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef BSIM_NRF_ARGS_H
+#define BSIM_NRF_ARGS_H
+
+#include <stdint.h>
+#include "NRF_hw_args.h"
+#include "bs_cmd_line.h"
+#include "bs_cmd_line_typical.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nrf52_bsim_args_t {
+    BS_BASIC_DEVICE_OPTIONS_FIELDS
+    nrf_hw_sub_args_t nrf_hw;
+};
+
+struct nrf52_bsim_args_t *nrfbsim_argsparse(int argc, char *argv[]);
+void nrfbsim_register_args(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/babblesim/core/include/cmsis.h b/babblesim/core/include/cmsis.h
new file mode 100644
index 0000000..8f9a6a3
--- /dev/null
+++ b/babblesim/core/include/cmsis.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2020 Oticon A/S
+ * Copyright (c) 2021 Codecoup
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * This header defines replacements for inline
+ * ARM Cortex-M CMSIS intrinsics.
+ */
+
+#ifndef BOARDS_POSIX_NRF52_BSIM_CMSIS_H
+#define BOARDS_POSIX_NRF52_BSIM_CMSIS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Implement the following ARM intrinsics as no-op:
+ * - ARM Data Synchronization Barrier
+ * - ARM Data Memory Synchronization Barrier
+ * - ARM Instruction Synchronization Barrier
+ * - ARM No Operation
+ */
+#ifndef __DMB
+#define __DMB()
+#endif
+
+#ifndef __DSB
+#define __DSB()
+#endif
+
+#ifndef __ISB
+#define __ISB()
+#endif
+
+#ifndef __NOP
+#define __NOP()
+#endif
+
+void NVIC_SystemReset(void);
+void __disable_irq(void);
+void __enable_irq(void);
+uint32_t __get_PRIMASK(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BOARDS_POSIX_NRF52_BSIM_CMSIS_H */
diff --git a/babblesim/core/include/core_cm4.h b/babblesim/core/include/core_cm4.h
new file mode 100644
index 0000000..ef8f9c3
--- /dev/null
+++ b/babblesim/core/include/core_cm4.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020 Oticon A/S
+ * Copyright (c) 2021 Codecoup
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _BSIM_CORE_CM4_H
+#define _BSIM_CORE_CM4_H
+
+#include <stdint.h>
+
+/* Include the original ext_NRF52_hw_models core_cm4.h */
+#include <../HW_models/core_cm4.h>
+
+/* Add missing function definitions */
+extern void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority);
+extern void NVIC_EnableIRQ(IRQn_Type IRQn);
+extern void NVIC_DisableIRQ(IRQn_Type IRQn);
+
+void __WFI(void);
+
+#ifndef __REV
+#define __REV __builtin_bswap32
+#endif
+
+#endif
diff --git a/babblesim/core/include/time_machine.h b/babblesim/core/include/time_machine.h
new file mode 100644
index 0000000..da28d01
--- /dev/null
+++ b/babblesim/core/include/time_machine.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Oticon A/S
+ * Copyright (c) 2021 Codecoup
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _TIME_MACHINE_H
+#define _TIME_MACHINE_H
+
+#include "bs_types.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+extern bs_time_t now;
+bs_time_t tm_get_abs_time(void);
+bs_time_t tm_get_hw_time(void);
+bs_time_t tm_hw_time_to_abs_time(bs_time_t hwtime);
+bs_time_t tm_abs_time_to_hw_time(bs_time_t abstime);
+
+void tm_reset_hw_times(void);
+
+void tm_find_next_timer_to_trigger(void);
+bs_time_t tm_get_next_timer_abstime(void);
+
+void tm_update_last_phy_sync_time(bs_time_t abs_time);
+
+void tm_set_phy_max_resync_offset(bs_time_t offset_in_us);
+
+void tm_run_forever(void);
+
+void tm_sleep_until_hw_time(bs_time_t hw_time);
+
+void tm_sleep_until_abs_time(bs_time_t time);
+
+void tm_start(void);
+
+void tm_tick(void);
+
+void tm_tick_limited(bs_time_t max_time_diff);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/babblesim/core/pkg.yml b/babblesim/core/pkg.yml
new file mode 100644
index 0000000..3b0c2e9
--- /dev/null
+++ b/babblesim/core/pkg.yml
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+pkg.name: babblesim/core
+pkg.type: sdk
+pkg.description: time machine, irq handeler, core
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+  - "@apache-mynewt-core/kernel/os"
+  - "@apache-mynewt-nimble/nimble/controller"
+  - "@apache-mynewt-nimble/nimble/transport"
+  - "babblesim/hw/babblesim"
+
+pkg.req_apis:
+  - ble_transport
+
+pkg.init:
+  bsim_start: 9999
diff --git a/babblesim/core/src/argparse.c b/babblesim/core/src/argparse.c
new file mode 100644
index 0000000..68f13de
--- /dev/null
+++ b/babblesim/core/src/argparse.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2017 Oticon A/S
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdbool.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "bs_tracing.h"
+#include "bs_oswrap.h"
+#include "bs_dump_files.h"
+#include "argparse.h"
+#include "NRF_hw_args.h"
+#include "bs_cmd_line.h"
+#include "bs_dynargs.h"
+#include "bs_cmd_line_typical.h"
+#include "NRF_HWLowL.h"
+
+static bs_args_struct_t *args_struct;
+static struct nrf52_bsim_args_t arg;
+const char *bogus_sim_id = "bogus";
+
+static void cmd_trace_lvl_found(char *argv, int offset)
+{
+	bs_trace_set_level(arg.verb);
+}
+
+static void cmd_gdev_nbr_found(char *argv, int offset)
+{
+	bs_trace_set_prefix_dev(arg.global_device_nbr);
+}
+
+static bool nosim;
+static void cmd_nosim_found(char *argv, int offset)
+{
+	hwll_set_nosim(true);
+}
+
+static void print_no_sim_warning(void)
+{
+	bs_trace_warning("Neither simulation id or the device number "
+			"have been set. I assume you want to run "
+			"without a BabbleSim phy (-nosim)\n");
+	bs_trace_warning("If this is not what you wanted, check with "
+			"--help how to set them\n");
+	bs_trace_raw(3, "setting sim_id to 'bogus', device number to 0 "
+			"and nosim\n");
+}
+
+void nrfbsim_register_args(void)
+{
+#define args (&arg)
+	/* This define is quite ugly, but allows reusing the definitions
+	 * provided by the utils library */
+	static bs_args_struct_t args_struct_toadd[] = {
+		ARG_TABLE_S_ID,
+		ARG_TABLE_P_ID_2G4,
+		ARG_TABLE_DEV_NBR,
+		ARG_TABLE_GDEV_NBR,
+		ARG_TABLE_VERB,
+		ARG_TABLE_SEED,
+		ARG_TABLE_COLOR,
+		ARG_TABLE_NOCOLOR,
+		ARG_TABLE_FORCECOLOR,
+		_NRF_HW_SUB_CMD_ARG_STRUCT,
+		/*
+		 * Fields:
+		 * manual, mandatory, switch,
+		 * option_name, var_name, type,
+		 * destination, callback,
+		 * description
+		 */
+		{false, false, true,
+		"nosim", "", 'b',
+		(void *)&nosim, cmd_nosim_found,
+		"(debug feature) Do not connect to the phy"},
+		BS_DUMP_FILES_ARGS,
+		{true, false, false,
+		"argsmain", "arg", 'l',
+		NULL, NULL,
+		"The arguments that follow will be passed to main (default)"},
+		ARG_TABLE_ENDMARKER
+	};
+#undef args
+
+	bs_add_dynargs(&args_struct, args_struct_toadd);
+}
+
+/**
+ * Check the arguments provided in the command line: set args based on it or
+ * defaults, and check they are correct
+ */
+struct nrf52_bsim_args_t *nrfbsim_argsparse(int argc, char *argv[])
+{
+	bs_args_set_defaults(args_struct);
+	arg.verb = 2;
+	bs_trace_set_level(arg.verb);
+	nrf_hw_sub_cmline_set_defaults(&arg.nrf_hw);
+	static const char default_phy[] = "2G4";
+
+    for (int i = 1; i < argc; i++) {
+        if (bs_is_option(argv[i], "argsmain", 0)) {
+            continue;
+        }
+
+        if (!bs_args_parse_one_arg(argv[i], args_struct)) {
+            bs_args_print_switches_help(args_struct);
+            bs_trace_error_line("Incorrect option %s\n",
+                                argv[i]);
+        }
+    }
+
+	/**
+	 * If the user did not set the simulation id or device number
+	 * we assume he wanted to run with nosim (but warn him)
+	 */
+	if ((!nosim) && (arg.s_id == NULL) && (arg.device_nbr == UINT_MAX)) {
+		print_no_sim_warning();
+		nosim = true;
+		hwll_set_nosim(true);
+	}
+	if (nosim) {
+		if (arg.s_id == NULL) {
+			arg.s_id = (char *)bogus_sim_id;
+		}
+		if (arg.device_nbr == UINT_MAX) {
+			arg.device_nbr = 0;
+		}
+	}
+
+	if (arg.device_nbr == UINT_MAX) {
+		bs_args_print_switches_help(args_struct);
+		bs_trace_error_line("The command line option <device number> "
+				    "needs to be set\n");
+	}
+	if (arg.global_device_nbr == UINT_MAX) {
+		arg.global_device_nbr = arg.device_nbr;
+		bs_trace_set_prefix_dev(arg.global_device_nbr);
+	}
+	if (!arg.s_id) {
+		bs_args_print_switches_help(args_struct);
+		bs_trace_error_line("The command line option <simulation ID> "
+				    "needs to be set\n");
+	}
+	if (!arg.p_id) {
+		arg.p_id = (char *)default_phy;
+	}
+
+	if (arg.rseed == UINT_MAX) {
+		arg.rseed = 0x1000 + arg.device_nbr;
+	}
+	return &arg;
+}
diff --git a/babblesim/core/src/cmsis.c b/babblesim/core/src/cmsis.c
new file mode 100644
index 0000000..622676c
--- /dev/null
+++ b/babblesim/core/src/cmsis.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ * Copyright (c) 2020 Oticon A/S
+ * Copyright (c) 2021 Codecoup
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include "irq_ctrl.h"
+
+#include "irq_sources.h"
+#include <nrfx.h>
+#include "cmsis.h"
+#include "os/sim.h"
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "irq_sources.h"
+#include <nrfx.h>
+#include "cmsis.h"
+
+extern void (* systemVectors[256])(void);
+
+/*
+ *  Replacement for ARMs NVIC functions()
+ */
+void NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+	hw_irq_ctrl_raise_im_from_sw(IRQn);
+}
+
+void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+	hw_irq_ctrl_clear_irq(IRQn);
+}
+
+void NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+	hw_irq_ctrl_disable_irq(IRQn);
+}
+
+void NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+	hw_irq_ctrl_enable_irq(IRQn);
+}
+
+void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+	hw_irq_ctrl_prio_set(IRQn, priority);
+}
+
+uint32_t NVIC_GetPriority(IRQn_Type IRQn)
+{
+	return hw_irq_ctrl_get_prio(IRQn);
+}
+
+void NVIC_SystemReset(void)
+{
+	inner_main_clean_up(1);
+}
+
+/*
+ * Replacements for some other CMSIS functions
+ */
+void __enable_irq(void)
+{
+	hw_irq_ctrl_change_lock(false);
+}
+
+void __disable_irq(void)
+{
+	hw_irq_ctrl_change_lock(true);
+}
+
+uint32_t __get_PRIMASK(void)
+{
+	return hw_irq_ctrl_get_current_lock();
+}
+
+void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+	systemVectors[(int32_t)IRQn + 16] = (void(*)(void))vector;
+}
diff --git a/babblesim/core/src/irq_handler.c b/babblesim/core/src/irq_handler.c
new file mode 100644
index 0000000..805d7ec
--- /dev/null
+++ b/babblesim/core/src/irq_handler.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017 Oticon A/S
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * SW side of the IRQ handling
+ */
+
+#include <stdint.h>
+#include "irq_ctrl.h"
+#include "irq_sources.h"
+#include "os/sim.h"
+
+static int currently_running_irq = -1;
+extern void (* const systemVectors[256])(void);
+
+/**
+ * When an interrupt is raised, this function is called to handle it and, if
+ * needed, swap to a re-enabled thread
+ *
+ * Note that even that this function is executing in a Zephyr thread,  it is
+ * effectively the model of the interrupt controller passing context to the IRQ
+ * handler and therefore its priority handling
+ */
+
+void posix_interrupt_raised(void)
+{
+    uint64_t irq_lock;
+    int irq_nbr;
+
+    irq_lock = hw_irq_ctrl_get_current_lock();
+
+    if (irq_lock) {
+        /* "spurious" wakes can happen with interrupts locked */
+        return;
+    }
+
+    while ((irq_nbr = hw_irq_ctrl_get_highest_prio_irq()) != -1) {
+        int last_current_running_prio = hw_irq_ctrl_get_cur_prio();
+        int last_running_irq = currently_running_irq;
+
+        hw_irq_ctrl_set_cur_prio(hw_irq_ctrl_get_prio(irq_nbr));
+        hw_irq_ctrl_clear_irq(irq_nbr);
+
+        currently_running_irq = irq_nbr;
+        systemVectors[irq_nbr + 16]();
+        currently_running_irq = last_running_irq;
+
+        hw_irq_ctrl_set_cur_prio(last_current_running_prio);
+    }
+}
+
+/**
+ * Thru this function the IRQ controller can raise an immediate  interrupt which
+ * will interrupt the SW itself
+ * (this function should only be called from the HW model code, from SW threads)
+ */
+void posix_irq_handler_im_from_sw(void)
+{
+	int sr = 0;
+
+	sr = sig_block_irq_on();
+	/*
+	 * if a higher priority interrupt than the possibly currently running is
+	 * pending we go immediately into irq_handler() to vector into its
+	 * handler
+	 */
+	if (hw_irq_ctrl_get_highest_prio_irq() != -1) {
+	    posix_interrupt_raised();
+	}
+	if (sr) {
+	    sig_unblock_irq_off();
+	}
+}
diff --git a/babblesim/core/src/main_config.c b/babblesim/core/src/main_config.c
new file mode 100644
index 0000000..4116e07
--- /dev/null
+++ b/babblesim/core/src/main_config.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017-2018 Oticon A/S
+ * Copyright (c) 2021 Codecoup
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "NRF_HW_model_top.h"
+#include "NRF_HWLowL.h"
+#include "bs_tracing.h"
+#include "bs_symbols.h"
+#include "bs_types.h"
+#include "bs_rand_main.h"
+#include "bs_pc_backchannel.h"
+#include "bs_dump_files.h"
+#include "argparse.h"
+#include "time_machine.h"
+#include "os/mynewt.h"
+#include <stdio.h>
+#include "os/sim.h"
+
+uint global_device_nbr;
+struct nrf52_bsim_args_t *args;
+
+void
+bst_tick(bs_time_t time)
+{
+    return;
+}
+
+uint8_t
+inner_main_clean_up(int exit_code)
+{
+    hwll_terminate_simulation();
+    nrf_hw_models_free_all();
+    bs_dump_files_close_all();
+
+    bs_clean_back_channels();
+    return 0;
+}
+
+uint8_t
+main_clean_up_trace_wrap(void)
+{
+    return inner_main_clean_up(0);
+}
+
+void
+bsim_init(int argc, char** argv, int (*main_fn)(int argc, char **arg))
+{
+        setvbuf(stdout, NULL, _IOLBF, 512);
+        setvbuf(stderr, NULL, _IOLBF, 512);
+
+        bs_trace_register_cleanup_function(main_clean_up_trace_wrap);
+        bs_trace_register_time_function(tm_get_abs_time);
+
+        nrf_hw_pre_init();
+        nrfbsim_register_args();
+
+        args = nrfbsim_argsparse(argc, argv);
+        global_device_nbr = args->global_device_nbr;
+
+        bs_read_function_names_from_Tsymbols(argv[0]);
+
+        nrf_hw_initialize(&args->nrf_hw);
+        os_init(main_fn);
+        os_start();
+}
+
+void
+bsim_start(void)
+{
+    bs_trace_raw(9, "%s: Connecting to phy...\n", __func__);
+    hwll_connect_to_phy(args->device_nbr, args->s_id, args->p_id);
+    bs_trace_raw(9, "%s: Connected\n", __func__);
+
+    bs_random_init(args->rseed);
+    bs_dump_files_open(args->s_id, args->global_device_nbr);
+}
diff --git a/babblesim/core/src/time_machine.c b/babblesim/core/src/time_machine.c
new file mode 100644
index 0000000..38b3f42
--- /dev/null
+++ b/babblesim/core/src/time_machine.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2017-2018 Oticon A/S
+ * Copyright (c) 2021 Codecoup
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "NRF_HW_model_top.h"
+#include "NRF_HWLowL.h"
+#include "bs_tracing.h"
+#include "bs_types.h"
+#include "bs_utils.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+
+/* Note: All timers are relative to hw_time and NOT to 'now' */
+extern bs_time_t timer_nrf_main_timer;
+
+/* The events priorities are as in this list from top to bottom
+ * Priority being which timer executes first if several trigger at the same
+ * instant
+ */
+static enum {
+    NRF_HW_MAIN_TIMER = 0,
+    NUMBER_OF_TIMERS,
+    NONE
+} next_timer_index = NONE;
+
+static bs_time_t *Timer_list[NUMBER_OF_TIMERS] = {
+    &timer_nrf_main_timer,
+};
+static bs_time_t next_timer_time = TIME_NEVER;
+
+/*
+ * Current absolute time of this device, as the device knows it.
+ * It is never reset:
+ */
+bs_time_t now;
+/* Current time the HW of this device things it is */
+static bs_time_t hw_time;
+/*
+ * Offset between the current absolute time of the device and the HW time
+ * That is, the absolute time when the HW_time got reset
+ */
+static bs_time_t hw_time_delta;
+
+/* Last time we synchronized with the bsim PHY, in device abs time */
+static bs_time_t last_bsim_phy_sync_time;
+
+#define BSIM_DEFAULT_PHY_MAX_RESYNC_OFFSET 1000000
+/* At least every second we will inform the simulator about our timing */
+static bs_time_t max_resync_offset = BSIM_DEFAULT_PHY_MAX_RESYNC_OFFSET;
+
+/**
+ * Set the maximum amount of time the device will spend without talking
+ * (synching) with the phy.
+ * This does not change the functional behavior of the Zephyr code or of the
+ * radio emulation, and it is only relevant if special test code running in the
+ * device interacts behind the scenes with other devices test code.
+ * Setting for example a value of 5ms will ensure that this device time
+ * will never be more than 5ms away from the phy. Setting it in all devices
+ * to 5ms would then ensure no device time is farther apart than 5ms from any
+ * other.
+ *
+ * Note that setting low values has a performance penalty.
+ */
+void
+tm_set_phy_max_resync_offset(bs_time_t offset_in_us)
+{
+    max_resync_offset = offset_in_us;
+}
+
+/**
+ * Return the absolute current time (no HW model except the RADIO
+ * should look into this)
+ */
+bs_time_t
+tm_get_abs_time(void)
+{
+    return now;
+}
+
+/**
+ * Return the current HW time
+ */
+bs_time_t
+tm_get_hw_time(void)
+{
+    return hw_time;
+}
+
+bs_time_t
+posix_get_hw_cycle(void)
+{
+    return tm_get_hw_time();
+}
+
+/**
+ * Reset the HW time
+ */
+static void
+tm_reset_hw_time(void)
+{
+    hw_time = 0;
+    hw_time_delta = now;
+    if (now != 0) {
+        bs_trace_error_line("Reset not supposed to happen after "
+                            "initialization\n");
+    }
+}
+
+/**
+ * Update the current hw_time value given the absolute time
+ */
+INLINE void
+tm_update_HW_time(void)
+{
+    hw_time = now - hw_time_delta;
+}
+
+/*
+ * Reset the HW time
+ */
+void
+tm_reset_hw_times(void)
+{
+    tm_reset_hw_time();
+}
+
+/**
+ * Advance the internal time values of this device until time
+ */
+void
+tm_sleep_until_abs_time(bs_time_t time)
+{
+    if (time >= now) {
+        /*
+         * Ensure that at least we sync with the phy
+         * every max_resync_offset
+         */
+        if (time > last_bsim_phy_sync_time + max_resync_offset) {
+            hwll_sync_time_with_phy(time);
+            last_bsim_phy_sync_time = time;
+        }
+
+        now = time;
+    } else {
+        /* LCOV_EXCL_START */
+        bs_trace_warning_manual_time_line(now, "next_time_time "
+                                               "corrupted (%"PRItime"<= %"PRItime", timer idx=%i)\n",
+                                          time, now, next_timer_index);
+        /* LCOV_EXCL_STOP */
+    }
+    tm_update_HW_time();
+}
+
+/**
+ * Keep track of the last time we synchronized the time with the scheduler
+ */
+void
+tm_update_last_phy_sync_time(bs_time_t abs_time)
+{
+    last_bsim_phy_sync_time = abs_time;
+}
+
+/**
+ * Advance the internal time values of this device
+ * until the HW time reaches hw_time
+ */
+void
+tm_sleep_until_hw_time(bs_time_t hw_time)
+{
+    bs_time_t next_time = TIME_NEVER;
+
+    if (hw_time != TIME_NEVER) {
+        next_time = hw_time + hw_time_delta;
+    }
+
+    tm_sleep_until_abs_time(next_time);
+}
+
+/**
+ * Look into all timers and update next_timer accordingly
+ * To be called each time a "timed process" updates its timer
+ */
+void
+tm_find_next_timer_to_trigger(void)
+{
+    next_timer_time = *Timer_list[0];
+    next_timer_index = 0;
+
+    for (uint i = 1; i < NUMBER_OF_TIMERS; i++) {
+        if (next_timer_time > *Timer_list[i]) {
+            next_timer_time = *Timer_list[i];
+            next_timer_index = i;
+        }
+    }
+}
+
+bs_time_t
+tm_get_next_timer_abstime(void)
+{
+    return next_timer_time + hw_time_delta;
+}
+
+bs_time_t
+tm_hw_time_to_abs_time(bs_time_t hwtime)
+{
+    if (hwtime == TIME_NEVER) {
+        return TIME_NEVER;
+    }
+    return hwtime + hw_time_delta;
+}
+
+bs_time_t
+tm_abs_time_to_hw_time(bs_time_t abstime)
+{
+    if (abstime == TIME_NEVER) {
+        return TIME_NEVER;
+    }
+    return abstime - hw_time_delta;
+}
+
+void
+tm_tick_limited(bs_time_t max_time_diff)
+{
+    bs_time_t time_to_wait;
+
+    if (max_time_diff != TIME_NEVER && now + max_time_diff < next_timer_time) {
+        time_to_wait = now + max_time_diff;
+    } else {
+        time_to_wait = next_timer_time;
+    }
+
+    tm_sleep_until_hw_time(time_to_wait);
+    switch (next_timer_index) {
+        case NRF_HW_MAIN_TIMER:
+            nrf_hw_some_timer_reached();
+            break;
+        default:
+            bs_trace_error_time_line("next_timer_index "
+                                     "corrupted\n");
+            break;
+    }
+    tm_find_next_timer_to_trigger();
+}
+
+void
+tm_tick(void)
+{
+    tm_tick_limited(TIME_NEVER);
+}
diff --git a/babblesim/hw/babblesim/pkg.yml b/babblesim/hw/babblesim/pkg.yml
new file mode 100644
index 0000000..ad28efb
--- /dev/null
+++ b/babblesim/hw/babblesim/pkg.yml
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+
+pkg.name: babblesim/hw/babblesim
+pkg.description: BabbleSim stuff
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+
+pkg.type: sdk
+
+pkg.include_dirs:
+  - components/ext_NRF52_hw_models/src/nrfx/mdk_replacements
+  - components/ext_NRF52_hw_models/src/HW_models
+  - components/ext_NRF52_hw_models/src/nrfx_config
+  - components/ext_NRF52_hw_models/src/nrfx/nrfx_replacements
+  - components/libUtilv1/src/
+  - components/libPhyComv1/src/
+  - components/libRandv2/src/
+  - components/ext_libCryptov1/src/
+
+pkg.src_dirs:
+  - src
+
+pkg.pre_build_cmds:
+  scripts/pre_build1.sh: 1
+
+pkg.lflags:
+  - -ldl
\ No newline at end of file
diff --git a/babblesim/hw/babblesim/scripts/pre_build1.sh b/babblesim/hw/babblesim/scripts/pre_build1.sh
new file mode 100755
index 0000000..3f3fec5
--- /dev/null
+++ b/babblesim/hw/babblesim/scripts/pre_build1.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+#
+# 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.
+#
+
+if [ -z ${BSIM_COMPONENTS_PATH+x} ]; then
+  echo "This board requires the BabbleSim simulator. Please set" \
+        "the environment variable BSIM_COMPONENTS_PATH to point to its components" \
+        "folder. More information can be found in" \
+        "https://babblesim.github.io/folder_structure_and_env.html"
+  exit 1
+fi
+
+if [ -z ${BSIM_OUT_PATH+x} ]; then
+  echo "This board requires the BabbleSim simulator. Please set" \
+        "the environment variable BSIM_OUT_PATH to point to the folder where the" \
+        "simulator is compiled to. More information can be found in" \
+        "https://babblesim.github.io/folder_structure_and_env.html"
+  exit 1
+fi
+
+if [[ -d "$(pwd)/components" ]]
+then
+    echo "Babblesim components: Directory exists. Removing and linking again..."
+    rm -r $(pwd)/components
+else
+    echo "Babblesim components: Linking components..."
+fi
+
+ln -nsf $BSIM_OUT_PATH/components
+
+if [[ -d "$(pwd)/src" ]]
+then
+    echo "Babblesim libraries src: Directory exists. Removing and linking again..."
+    rm -r $(pwd)/src
+else
+    echo "Babblesim components: Linking components..."
+fi
+
+mkdir -p src
+ln -nsf $BSIM_OUT_PATH/components
+
+# Create links to all .32.a files
+# find $BSIM_OUT_PATH/lib/$lib -name "*.32.a" -type f -exec ln -t src -nsf {} \;
+
+# Copy all .32.a files
+find $BSIM_OUT_PATH/lib/$lib -name "*.32.a" -type f -exec cp -t src -f {} \;
+
+# XXX: Workaround for bad linking by newt. Sometimes newt will link
+# nrf weak functions from nrf_hal_originals.o instead of their BabbleSim
+# replacements inside libNRF52_hw_models.32.a. But as long as the other
+# weak functions, that do not have their replacements, are not used,
+# we can just remove the file from the .a library here.
+ar d src/libNRF52_hw_models.32.a nrf_hal_originals.o
diff --git a/babblesim/hw/bsp/nrf52_bsim/bsp.yml b/babblesim/hw/bsp/nrf52_bsim/bsp.yml
new file mode 100644
index 0000000..edd2189
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/bsp.yml
@@ -0,0 +1,60 @@
+#
+# 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.
+#
+
+bsp.name: "nRF52 DK"
+bsp.url: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52-DK
+bsp.maker: "Nordic Semiconductor"
+bsp.arch: bsim_arch
+bsp.compiler: "@apache-mynewt-core/compiler/sim"
+bsp.downloadscript: "hw/bsp/nrf52_bsim/nordic_pca10040_download.sh"
+bsp.debugscript: "hw/bsp/nrf52_bsim/nordic_pca10040_debug.sh"
+bsp.downloadscript.WINDOWS.OVERWRITE: "hw/bsp/nrf52_bsim/nordic_pca10040_download.cmd"
+bsp.debugscript.WINDOWS.OVERWRITE: "hw/bsp/nrf52_bsim/nordic_pca10040_debug.cmd"
+
+bsp.flash_map:
+    areas:
+        # System areas.
+        FLASH_AREA_BOOTLOADER:
+            device: 0
+            offset: 0x00000000
+            size: 16kB
+        FLASH_AREA_IMAGE_0:
+            device: 0
+            offset: 0x00008000
+            size: 232kB
+        FLASH_AREA_IMAGE_1:
+            device: 0
+            offset: 0x00042000
+            size: 232kB
+        FLASH_AREA_IMAGE_SCRATCH:
+            device: 0
+            offset: 0x0007c000
+            size: 4kB
+
+        # User areas.
+        FLASH_AREA_REBOOT_LOG:
+            user_id: 0
+            device: 0
+            offset: 0x00004000
+            size: 16kB
+        FLASH_AREA_NFFS:
+            user_id: 1
+            device: 0
+            offset: 0x0007d000
+            size: 12kB
diff --git a/babblesim/hw/bsp/nrf52_bsim/include/bsp/bsp.h b/babblesim/hw/bsp/nrf52_bsim/include/bsp/bsp.h
new file mode 100644
index 0000000..c096b88
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/include/bsp/bsp.h
@@ -0,0 +1,91 @@
+/*
+ * 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_BSP_H
+#define H_BSP_H
+
+#include <inttypes.h>
+
+#include "os/mynewt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Define special stackos sections */
+#define sec_data_core   __attribute__((section(".data.core")))
+#define sec_bss_core    __attribute__((section(".bss.core")))
+#define sec_bss_nz_core __attribute__((section(".bss.core.nz")))
+
+/* More convenient section placement macros. */
+#define bssnz_t         sec_bss_nz_core
+
+extern uint8_t _ram_start;
+#define RAM_SIZE        0x10000
+
+/* LED pins */
+#define LED_1           (17)
+#define LED_2           (18)
+#define LED_3           (19)
+#define LED_4           (20)
+#define LED_BLINK_PIN   (LED_1)
+
+/* Buttons */
+#define BUTTON_1 (13)
+#define BUTTON_2 (14)
+#define BUTTON_3 (15)
+#define BUTTON_4 (16)
+
+/* Arduino pins */
+#define ARDUINO_PIN_D0      11
+#define ARDUINO_PIN_D1      12
+#define ARDUINO_PIN_D2      13
+#define ARDUINO_PIN_D3      14
+#define ARDUINO_PIN_D4      15
+#define ARDUINO_PIN_D5      16
+#define ARDUINO_PIN_D6      17
+#define ARDUINO_PIN_D7      18
+#define ARDUINO_PIN_D8      19
+#define ARDUINO_PIN_D9      20
+#define ARDUINO_PIN_D10     22
+#define ARDUINO_PIN_D11     23
+#define ARDUINO_PIN_D12     24
+#define ARDUINO_PIN_D13     25
+#define ARDUINO_PIN_A0      3
+#define ARDUINO_PIN_A1      4
+#define ARDUINO_PIN_A2      28
+#define ARDUINO_PIN_A3      29
+#define ARDUINO_PIN_A4      30
+#define ARDUINO_PIN_A5      31
+
+#define ARDUINO_PIN_RX      ARDUINO_PIN_D0
+#define ARDUINO_PIN_TX      ARDUINO_PIN_D1
+
+#define ARDUINO_PIN_SCL     27
+#define ARDUINO_PIN_SDA     26
+
+#define ARDUINO_PIN_SCK     ARDUINO_PIN_D13
+#define ARDUINO_PIN_MOSI    ARDUINO_PIN_D11
+#define ARDUINO_PIN_MISO    ARDUINO_PIN_D12
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* H_BSP_H */
diff --git a/babblesim/hw/bsp/nrf52_bsim/include/os/os_arch.h b/babblesim/hw/bsp/nrf52_bsim/include/os/os_arch.h
new file mode 100644
index 0000000..32bc97b
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/include/os/os_arch.h
@@ -0,0 +1,64 @@
+/*
+ * 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 _OS_ARCH_ARM_H
+#define _OS_ARCH_ARM_H
+
+#include <stdint.h>
+#include "syscfg/syscfg.h"
+#include "mcu/cmsis_nvic.h"
+#include "mcu/cortex_m4.h"
+#include <irq_ctrl.h>
+#include "mcu/mcu_sim.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* CPU status register */
+typedef uint32_t os_sr_t;
+
+/* Stack element */
+typedef uint32_t os_stack_t;
+
+struct stack_frame;
+void os_arch_frame_init(struct stack_frame *sf);
+
+/* Stack sizes for common OS tasks */
+#define OS_SANITY_STACK_SIZE (2000)
+#if MYNEWT_VAL(OS_SYSVIEW)
+#define OS_IDLE_STACK_SIZE (80)
+#else
+#define OS_IDLE_STACK_SIZE (4000)
+#endif
+
+static inline int
+os_arch_in_isr(void)
+{
+	return hw_irq_ctrl_get_irq_status();
+}
+
+/* Include common arch definitions and APIs */
+#include "os/arch/common.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_ARCH_ARM_H */
diff --git a/babblesim/hw/bsp/nrf52_bsim/include/os/sim.h b/babblesim/hw/bsp/nrf52_bsim/include/os/sim.h
new file mode 100644
index 0000000..3d8837b
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/include/os/sim.h
@@ -0,0 +1,60 @@
+/*
+ * 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_KERNEL_SIM_
+#define H_KERNEL_SIM_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <setjmp.h>
+#include "os/mynewt.h"
+#include "mcu/mcu_sim.h"
+struct os_task;
+struct stack_frame;
+
+struct stack_frame {
+    int sf_mainsp;              /* stack on which main() is executing */
+    sigjmp_buf sf_jb;
+    struct os_task *sf_task;
+};
+
+void sim_task_start(struct stack_frame *sf, int rc);
+os_stack_t *sim_task_stack_init(struct os_task *t, os_stack_t *stack_top,
+                                int size);
+os_error_t sim_os_start(void);
+void sim_os_stop(void);
+os_error_t sim_os_init(void);
+void sim_ctx_sw(struct os_task *next_t);
+os_sr_t sim_save_sr(void);
+void sim_restore_sr(os_sr_t osr);
+int sim_in_critical(void);
+void sim_tick_idle(os_time_t ticks);
+int sig_block_irq_on();
+void sig_unblock_irq_off();
+
+uint8_t inner_main_clean_up(int exit_code);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_debug.cmd b/babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_debug.cmd
new file mode 100755
index 0000000..3444fd3
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_debug.cmd
@@ -0,0 +1,22 @@
+@rem
+@rem Licensed to the Apache Software Foundation (ASF) under one
+@rem or more contributor license agreements.  See the NOTICE file
+@rem distributed with this work for additional information
+@rem regarding copyright ownership.  The ASF licenses this file
+@rem to you under the Apache License, Version 2.0 (the
+@rem "License"); you may not use this file except in compliance
+@rem with the License.  You may obtain a copy of the License at
+@rem
+@rem  http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing,
+@rem software distributed under the License is distributed on an
+@rem "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@rem KIND, either express or implied.  See the License for the
+@rem specific language governing permissions and limitations
+@rem under the License.
+@rem
+
+@rem Execute a shell with a script of the same name and .sh extension
+
+@bash "%~dp0%~n0.sh"
diff --git a/babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_debug.sh b/babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_debug.sh
new file mode 100755
index 0000000..1e248e4
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_debug.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+# 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.
+#
+
+# Called with following variables set:
+#  - CORE_PATH is absolute path to @apache-mynewt-core
+#  - BSP_PATH is absolute path to hw/bsp/bsp_name
+#  - BIN_BASENAME is the path to prefix to target binary,
+#    .elf appended to name is the ELF file
+#  - FEATURES holds the target features string
+#  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
+#  - RESET set if target should be reset when attaching
+#  - NO_GDB set if we should not start gdb to debug
+#
+
+. $CORE_PATH/hw/scripts/jlink.sh
+
+FILE_NAME=$BIN_BASENAME.elf
+
+if [ $# -gt 2 ]; then
+    SPLIT_ELF_NAME=$3.elf
+    # TODO -- this magic number 0x42000 is the location of the second image
+    # slot. we should either get this from a flash map file or somehow learn
+    # this from the image itself
+    EXTRA_GDB_CMDS="add-symbol-file $SPLIT_ELF_NAME 0x8000 -readnow"
+fi
+
+JLINK_DEV="nRF52"
+
+jlink_debug
diff --git a/babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_download.cmd b/babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_download.cmd
new file mode 100755
index 0000000..3444fd3
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_download.cmd
@@ -0,0 +1,22 @@
+@rem
+@rem Licensed to the Apache Software Foundation (ASF) under one
+@rem or more contributor license agreements.  See the NOTICE file
+@rem distributed with this work for additional information
+@rem regarding copyright ownership.  The ASF licenses this file
+@rem to you under the Apache License, Version 2.0 (the
+@rem "License"); you may not use this file except in compliance
+@rem with the License.  You may obtain a copy of the License at
+@rem
+@rem  http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing,
+@rem software distributed under the License is distributed on an
+@rem "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@rem KIND, either express or implied.  See the License for the
+@rem specific language governing permissions and limitations
+@rem under the License.
+@rem
+
+@rem Execute a shell with a script of the same name and .sh extension
+
+@bash "%~dp0%~n0.sh"
diff --git a/babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_download.sh b/babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_download.sh
new file mode 100755
index 0000000..08d45b4
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/nordic_pca10040_download.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+# 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.
+
+# Called with following variables set:
+#  - CORE_PATH is absolute path to @apache-mynewt-core
+#  - BSP_PATH is absolute path to hw/bsp/bsp_name
+#  - BIN_BASENAME is the path to prefix to target binary,
+#    .elf appended to name is the ELF file
+#  - IMAGE_SLOT is the image slot to download to (for non-mfg-image, non-boot)
+#  - FEATURES holds the target features string
+#  - EXTRA_JTAG_CMD holds extra parameters to pass to jtag software
+#  - MFG_IMAGE is "1" if this is a manufacturing image
+#  - FLASH_OFFSET contains the flash offset to download to
+#  - BOOT_LOADER is set if downloading a bootloader
+
+. $CORE_PATH/hw/scripts/jlink.sh
+
+if [ "$MFG_IMAGE" ]; then
+    FLASH_OFFSET=0x0
+fi
+
+JLINK_DEV="nRF52"
+
+common_file_to_load
+jlink_load
diff --git a/babblesim/hw/bsp/nrf52_bsim/pkg.yml b/babblesim/hw/bsp/nrf52_bsim/pkg.yml
new file mode 100644
index 0000000..6662a76
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/pkg.yml
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+pkg.name: babblesim/hw/bsp/nrf52_bsim
+pkg.type: bsp
+pkg.description: nRF52 on BabbleSim
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+
+pkg.cflags:
+    - '-DNRF52832_XXAA'
+    - '-DBABBLESIM'
+
+pkg.cflags.HARDFLOAT:
+    - -mfloat-abi=hard -mfpu=fpv4-sp-d16
+
+pkg.deps:
+    - "@apache-mynewt-core/hw/drivers/uart/uart_hal"
+    - "babblesim/hw/mcu/nordic/nrf52_bsim"
+    - "babblesim/hw/babblesim"
+    - "babblesim/core"
diff --git a/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/os_arch.c b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/os_arch.c
new file mode 100644
index 0000000..6700e90
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/os_arch.c
@@ -0,0 +1,110 @@
+/*
+ * 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 "os/mynewt.h"
+#include "os/sim.h"
+#include "sim_priv.h"
+#include <irq_ctrl.h>
+
+/*
+ * From HAL_CM4.s
+ */
+extern void SVC_Handler(void);
+extern void PendSV_Handler(void);
+extern void SysTick_Handler(void);
+
+/*
+ * Assert that 'sf_mainsp' and 'sf_jb' are at the specific offsets where
+ * os_arch_frame_init() expects them to be.
+ */
+CTASSERT(offsetof(struct stack_frame, sf_mainsp) == 0);
+CTASSERT(offsetof(struct stack_frame, sf_jb) == 4);
+
+void
+os_arch_task_start(struct stack_frame *sf, int rc)
+{
+    sim_task_start(sf, rc);
+}
+
+os_stack_t *
+os_arch_task_stack_init(struct os_task *t, os_stack_t *stack_top, int size)
+{
+    return sim_task_stack_init(t, stack_top, size);
+}
+
+os_error_t
+os_arch_os_start(void)
+{
+    return sim_os_start();
+}
+
+void
+os_arch_os_stop(void)
+{
+    sim_os_stop();
+}
+
+void
+PendSV_Handler(void)
+{
+    sim_switch_tasks();
+}
+
+os_error_t
+os_arch_os_init(void)
+{
+    NVIC_SetVector(PendSV_IRQn, (uint32_t)PendSV_Handler);
+    return sim_os_init();
+}
+
+void
+os_arch_ctx_sw(struct os_task *next_t)
+{
+    sim_ctx_sw(next_t);
+}
+
+os_sr_t
+os_arch_save_sr(void)
+{
+    sim_save_sr();
+    return hw_irq_ctrl_change_lock(1);
+}
+
+void
+os_arch_restore_sr(os_sr_t osr)
+{
+    hw_irq_ctrl_change_lock(osr);
+    sim_restore_sr(osr);
+}
+
+
+int
+os_arch_in_critical(void)
+{
+    return sim_in_critical();
+}
+
+void
+__assert_func(const char *file, int line, const char *func, const char *e)
+{
+#if MYNEWT_VAL(OS_ASSERT_CB)
+    os_assert_cb();
+#endif
+    _Exit(1);
+}
diff --git a/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/os_arch_stack_frame.s b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/os_arch_stack_frame.s
new file mode 100644
index 0000000..81e5c06
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/os_arch_stack_frame.s
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+#if defined MN_LINUX
+#define sigsetjmp   __sigsetjmp
+#define CNAME(x)    x
+#elif defined MN_OSX
+#define sigsetjmp   sigsetjmp
+#define CNAME(x)    _ ## x
+#elif defined MN_FreeBSD
+#define sigsetjmp   sigsetjmp
+#define CNAME(x)    x
+#else
+#error "unsupported platform"
+#endif
+
+    .text
+    .code32
+    .p2align 4, 0x90    /* align on 16-byte boundary and fill with NOPs */
+
+    .globl CNAME(os_arch_frame_init)
+    .globl _os_arch_frame_init
+    /*
+     * void os_arch_frame_init(struct stack_frame *sf)
+     */
+CNAME(os_arch_frame_init):
+    push    %ebp                    /* function prologue for backtrace */
+    mov     %esp,%ebp
+    push    %esi                    /* save %esi before using it as a tmpreg */
+
+    /*
+     * At this point we are executing on the main() stack:
+     * ----------------
+     * stack_frame ptr      0xc(%esp)
+     * ----------------
+     * return address       0x8(%esp)
+     * ----------------
+     * saved ebp            0x4(%esp)
+     * ----------------
+     * saved esi            0x0(%esp)
+     * ----------------
+     */
+    movl    0xc(%esp),%esi          /* %esi = 'sf' */
+    movl    %esp,0x0(%esi)          /* sf->mainsp = %esp */
+
+    /*
+     * Switch the stack so the stack pointer stored in 'sf->sf_jb' points
+     * to the task stack. This is slightly complicated because OS X wants
+     * the incoming stack pointer to be 16-byte aligned.
+     *
+     * ----------------
+     * sf (other fields)
+     * ----------------
+     * sf (sf_jb)           0x4(%esi)
+     * ----------------
+     * sf (sf_mainsp)       0x0(%esi)
+     * ----------------
+     * alignment padding    variable (0 to 12 bytes)
+     * ----------------
+     * savemask (0)         0x4(%esp)
+     * ----------------
+     * pointer to sf_jb     0x0(%esp)
+     * ----------------
+     */
+    movl    %esi,%esp
+    subl    $0x8,%esp               /* make room for sigsetjmp() arguments */
+    andl    $0xfffffff0,%esp        /* align %esp on 16-byte boundary */
+    leal    0x4(%esi),%eax          /* %eax = &sf->sf_jb */
+    movl    %eax,0x0(%esp)
+    movl    $0, 0x4(%esp)
+    call    CNAME(sigsetjmp)        /* sigsetjmp(sf->sf_jb, 0) */
+    test    %eax,%eax
+    jne     1f
+    movl    0x0(%esi),%esp          /* switch back to the main() stack */
+    pop     %esi
+    pop     %ebp
+    ret                             /* return to os_arch_task_stack_init() */
+1:
+    lea     2f,%ecx
+    push    %ecx                    /* retaddr */
+    push    $0                      /* frame pointer */
+    movl    %esp,%ebp               /* handcrafted prologue for backtrace */
+    push    %eax                    /* rc */
+    push    %esi                    /* sf */
+    call    CNAME(os_arch_task_start) /* os_arch_task_start(sf, rc) */
+    /* never returns */
+2:
+    nop
diff --git a/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_priv.h b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_priv.h
new file mode 100644
index 0000000..39984df
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_priv.h
@@ -0,0 +1,44 @@
+/*
+ * 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_SIM_PRIV_
+#define H_SIM_PRIV_
+
+#include <sys/types.h>
+#include "os/mynewt.h"
+#include "mcu/mcu_sim.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define OS_USEC_PER_TICK    (1000000 / OS_TICKS_PER_SEC)
+
+void sim_switch_tasks(void);
+void sim_tick(void);
+void sim_signals_init(void);
+void sim_signals_cleanup(void);
+
+extern pid_t sim_pid;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_sched_gen.c b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_sched_gen.c
new file mode 100644
index 0000000..b3c192f
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_sched_gen.c
@@ -0,0 +1,240 @@
+/*
+ * 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.
+ */
+
+/**
+ * This file contains code that is shared by both sim implementations (signals
+ * and no-signals).
+ */
+
+#include "os/mynewt.h"
+
+#include <hal/hal_bsp.h>
+
+#ifdef __APPLE__
+#define _XOPEN_SOURCE
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <assert.h>
+#include <hal/hal_os_tick.h>
+#include "os/sim.h"
+#include "sim_priv.h"
+
+#define sim_setjmp(__jb) sigsetjmp(__jb, 0)
+#define sim_longjmp(__jb, __ret) siglongjmp(__jb, __ret)
+
+pid_t sim_pid;
+
+void
+sim_switch_tasks(void)
+{
+    struct os_task *t, *next_t;
+    struct stack_frame *sf;
+    int rc;
+
+    OS_ASSERT_CRITICAL();
+
+    t = os_sched_get_current_task();
+    next_t = os_sched_next_task();
+    if (t == next_t) {
+        /*
+         * Context switch not needed - just return.
+         */
+        return;
+    }
+
+    if (t) {
+        sf = (struct stack_frame *) t->t_stackptr;
+
+        rc = sim_setjmp(sf->sf_jb);
+        if (rc != 0) {
+            OS_ASSERT_CRITICAL();
+            return;
+        }
+    }
+
+    os_sched_ctx_sw_hook(next_t);
+
+    os_sched_set_current_task(next_t);
+
+    sf = (struct stack_frame *) next_t->t_stackptr;
+    sim_longjmp(sf->sf_jb, 1);
+}
+
+void
+sim_tick(void)
+{
+    struct timeval time_now, time_diff;
+    int ticks;
+
+    static struct timeval time_last;
+    static int time_inited;
+
+    OS_ASSERT_CRITICAL();
+
+    if (!time_inited) {
+        gettimeofday(&time_last, NULL);
+        time_inited = 1;
+    }
+
+    gettimeofday(&time_now, NULL);
+    if (timercmp(&time_now, &time_last, <)) {
+        /*
+         * System time going backwards.
+         */
+        time_last = time_now;
+    } else {
+        timersub(&time_now, &time_last, &time_diff);
+
+        ticks = time_diff.tv_sec * OS_TICKS_PER_SEC;
+        ticks += time_diff.tv_usec / OS_USEC_PER_TICK;
+
+        /*
+         * Update 'time_last' but account for the remainder usecs that did not
+         * contribute towards whole 'ticks'.
+         */
+        time_diff.tv_sec = 0;
+        time_diff.tv_usec %= OS_USEC_PER_TICK;
+        timersub(&time_now, &time_diff, &time_last);
+
+        os_time_advance(ticks);
+    }
+}
+
+#define OS_TICK_PRIO 7
+
+static void
+sim_start_timer(void)
+{
+    /* Intitialize and start system clock timer */
+    os_tick_init(OS_TICKS_PER_SEC, OS_TICK_PRIO);
+}
+
+static void
+sim_stop_timer(void)
+{
+    struct itimerval it;
+    int rc;
+
+    memset(&it, 0, sizeof(it));
+
+    rc = setitimer(ITIMER_REAL, &it, NULL);
+    assert(rc == 0);
+}
+
+/*
+ * Called from 'os_arch_frame_init()' when setjmp returns indirectly via
+ * longjmp. The return value of setjmp is passed to this function as 'rc'.
+ */
+void
+sim_task_start(struct stack_frame *sf, int rc)
+{
+    struct os_task *task;
+
+    /*
+     * Interrupts are disabled when a task starts executing. This happens in
+     * two different ways:
+     * - via sim_os_start() for the first task.
+     * - via os_sched() for all other tasks.
+     *
+     * Enable interrupts before starting the task.
+     */
+    OS_EXIT_CRITICAL(0);
+
+    task = sf->sf_task;
+    task->t_func(task->t_arg);
+
+    /* A task handler should never return. */
+    assert(0);
+}
+
+os_stack_t *
+sim_task_stack_init(struct os_task *t, os_stack_t *stack_top, int size)
+{
+    struct stack_frame *sf;
+
+    sf = (struct stack_frame *) ((uint8_t *) stack_top - sizeof(*sf));
+    sf->sf_task = t;
+
+    os_arch_frame_init(sf);
+
+    return ((os_stack_t *)sf);
+}
+
+os_error_t
+sim_os_start(void)
+{
+    struct stack_frame *sf;
+    struct os_task *t;
+    os_sr_t sr;
+
+    /*
+     * Disable interrupts before enabling any interrupt sources. Pending
+     * interrupts will be recognized when the first task starts executing.
+     */
+    OS_ENTER_CRITICAL(sr);
+    assert(sr == 0);
+
+    /* Enable the interrupt sources */
+    sim_start_timer();
+
+    t = os_sched_next_task();
+    os_sched_set_current_task(t);
+
+    g_os_started = 1;
+
+    sf = (struct stack_frame *) t->t_stackptr;
+    sim_longjmp(sf->sf_jb, 1);
+
+    return 0;
+}
+
+/**
+ * Stops the tick timer and clears the "started" flag.  This function is only
+ * implemented for sim.
+ */
+void
+sim_os_stop(void)
+{
+    sim_stop_timer();
+    sim_signals_cleanup();
+    g_os_started = 0;
+}
+
+os_error_t
+sim_os_init(void)
+{
+    sim_pid = getpid();
+    g_current_task = NULL;
+
+    STAILQ_INIT(&g_os_task_list);
+    TAILQ_INIT(&g_os_run_list);
+    TAILQ_INIT(&g_os_sleep_list);
+
+    sim_signals_init();
+
+    os_init_idle_task();
+
+    return OS_OK;
+}
diff --git a/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_sched_nosig.c b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_sched_nosig.c
new file mode 100644
index 0000000..fadb712
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_sched_nosig.c
@@ -0,0 +1,238 @@
+/*
+ * 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.
+ */
+
+/**
+ * This file implements the "no-signals" version of sim.  This implementation
+ * does not use signals to perform context switches.  This is the less correct
+ * version of sim: the OS tick timer only runs while the idle task is active.
+ * Therefore, a sleeping high-priority task will not preempt a low-priority
+ * task due to a timing event (e.g., delay or callout expired).  However, this
+ * version of sim does not suffer from the stability issues that affect the
+ * "signals" implementation.
+ *
+ * To use this version of sim, disable the MCU_NATIVE_USE_SIGNALS syscfg
+ * setting.
+ */
+
+#include "os/mynewt.h"
+
+#if !MYNEWT_VAL(MCU_NATIVE_USE_SIGNALS)
+
+#include <hal/hal_bsp.h>
+
+#ifdef __APPLE__
+#define _XOPEN_SOURCE
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <assert.h>
+#include "sim_priv.h"
+
+static sigset_t nosigs;
+static sigset_t suspsigs;   /* signals delivered in sigsuspend() */
+
+static int ctx_sw_pending;
+static int interrupts_enabled = 1;
+
+void
+sim_ctx_sw(struct os_task *next_t)
+{
+    if (interrupts_enabled) {
+        /* Perform the context switch immediately. */
+        sim_switch_tasks();
+    } else {
+        /* Remember that we want to perform a context switch.  Perform it when
+         * interrupts are re-enabled.
+         */
+        ctx_sw_pending = 1;
+    }
+}
+
+/*
+ * Enter a critical section.
+ *
+ * Returns 1 if interrupts were already disabled; 0 otherwise.
+ */
+os_sr_t
+sim_save_sr(void)
+{
+    if (!interrupts_enabled) {
+        return 1;
+    }
+
+    interrupts_enabled = 0;
+    return 0;
+}
+
+void
+sim_restore_sr(os_sr_t osr)
+{
+    OS_ASSERT_CRITICAL();
+    assert(osr == 0 || osr == 1);
+
+    if (osr == 1) {
+        /* Exiting a nested critical section */
+        return;
+    }
+
+    if (ctx_sw_pending) {
+        /* A context switch was requested while interrupts were disabled.
+         * Perform it now that interrupts are enabled again.
+         */
+        ctx_sw_pending = 0;
+        sim_switch_tasks();
+    }
+    interrupts_enabled = 1;
+}
+
+int
+sim_in_critical(void)
+{
+    return !interrupts_enabled;
+}
+
+/**
+ * Unblocks the SIGALRM signal that is delivered by the OS tick timer.
+ */
+static void
+unblock_timer(void)
+{
+    sigset_t sigs;
+    int rc;
+
+    sigemptyset(&sigs);
+    sigaddset(&sigs, SIGALRM);
+
+    rc = sigprocmask(SIG_UNBLOCK, &sigs, NULL);
+    assert(rc == 0);
+}
+
+/**
+ * Blocks the SIGALRM signal that is delivered by the OS tick timer.
+ */
+static void
+block_timer(void)
+{
+    sigset_t sigs;
+    int rc;
+
+    sigemptyset(&sigs);
+    sigaddset(&sigs, SIGALRM);
+
+    rc = sigprocmask(SIG_BLOCK, &sigs, NULL);
+    assert(rc == 0);
+}
+
+static void
+sig_handler_alrm(int sig)
+{
+    /* Wake the idle task. */
+    sigaddset(&suspsigs, sig);
+}
+
+void
+sim_tick_idle(os_time_t ticks)
+{
+    int rc;
+    struct itimerval it;
+
+    OS_ASSERT_CRITICAL();
+
+    if (ticks > 0) {
+        /*
+         * Enter tickless regime and set the timer to fire after 'ticks'
+         * worth of time has elapsed.
+         */
+        it.it_value.tv_sec = ticks / OS_TICKS_PER_SEC;
+        it.it_value.tv_usec = (ticks % OS_TICKS_PER_SEC) * OS_USEC_PER_TICK;
+        it.it_interval.tv_sec = 0;
+        it.it_interval.tv_usec = OS_USEC_PER_TICK;
+        rc = setitimer(ITIMER_REAL, &it, NULL);
+        assert(rc == 0);
+    }
+
+    unblock_timer();
+
+    sigemptyset(&suspsigs);
+    sigsuspend(&nosigs);        /* Wait for a signal to wake us up */
+
+    block_timer();
+
+    /*
+     * Call handlers for signals delivered to the process during sigsuspend().
+     * The SIGALRM handler is called before any other handlers to ensure that
+     * OS time is always correct.
+     */
+    if (sigismember(&suspsigs, SIGALRM)) {
+        sim_tick();
+    }
+
+    if (ticks > 0) {
+        /*
+         * Enable the periodic timer interrupt.
+         */
+        it.it_value.tv_sec = 0;
+        it.it_value.tv_usec = OS_USEC_PER_TICK;
+        it.it_interval.tv_sec = 0;
+        it.it_interval.tv_usec = OS_USEC_PER_TICK;
+        rc = setitimer(ITIMER_REAL, &it, NULL);
+        assert(rc == 0);
+    }
+}
+
+void
+sim_signals_init(void)
+{
+    sigset_t sigset_alrm;
+    struct sigaction sa;
+    int error;
+
+    block_timer();
+
+    sigemptyset(&nosigs);
+
+    sigemptyset(&sigset_alrm);
+    sigaddset(&sigset_alrm, SIGALRM);
+
+    memset(&sa, 0, sizeof sa);
+    sa.sa_handler = sig_handler_alrm;
+    sa.sa_mask = sigset_alrm;
+    sa.sa_flags = SA_RESTART;
+    error = sigaction(SIGALRM, &sa, NULL);
+    assert(error == 0);
+}
+
+void
+sim_signals_cleanup(void)
+{
+    int error;
+    struct sigaction sa;
+
+    memset(&sa, 0, sizeof sa);
+    sa.sa_handler = SIG_DFL;
+    error = sigaction(SIGALRM, &sa, NULL);
+    assert(error == 0);
+}
+
+#endif /* !MYNEWT_VAL(MCU_NATIVE_USE_SIGNALS) */
diff --git a/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_sched_sig.c b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_sched_sig.c
new file mode 100644
index 0000000..c26abce
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/sim_sched_sig.c
@@ -0,0 +1,288 @@
+/*
+ * 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.
+ */
+
+/**
+ * This file implements the "signals" version of sim.  This implementation uses
+ * signals to perform context switches.  This is the more correct version of
+ * sim: the OS tick timer will cause a high-priority task to preempt a
+ * low-priority task.  Unfortunately, there are stability issues because a task
+ * can be preempted while it is in the middle of a system call, potentially
+ * causing deadlock or memory corruption.
+ *
+ * To use this version of sim, enable the MCU_NATIVE_USE_SIGNALS syscfg
+ * setting.
+ */
+
+#include "os/mynewt.h"
+
+#if MYNEWT_VAL(MCU_NATIVE_USE_SIGNALS)
+
+#include "sim_priv.h"
+
+#include <hal/hal_bsp.h>
+
+#ifdef __APPLE__
+#define _XOPEN_SOURCE
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <assert.h>
+
+static bool suspended;      /* process is blocked in sigsuspend() */
+static sigset_t suspsigs;   /* signals delivered in sigsuspend() */
+static sigset_t allsigs;
+static sigset_t nosigs;
+
+static int in_irq;
+int counter = 0;
+
+int
+sig_block_irq_on()
+{
+	int error;
+
+    counter++;
+
+	error = sigprocmask(SIG_BLOCK, &allsigs, NULL);
+
+	in_irq = 1;
+	assert(error == 0);
+	return 1;
+}
+
+void
+sig_unblock_irq_off()
+{
+	int error;
+
+	in_irq = 0;
+
+	if (counter > 0) {
+	    counter--;
+	    return;
+	}
+
+	error = sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
+	assert(error == 0);
+
+}
+
+void
+sim_ctx_sw(struct os_task *next_t)
+{
+    /*
+     * gdb will stop execution of the program on most signals (e.g. SIGUSR1)
+     * whereas it passes SIGURG to the process without any special settings.
+     */
+    kill(sim_pid, SIGURG);
+}
+
+static void
+ctxsw_handler(int sig)
+{
+    assert(in_irq==0);
+    OS_ASSERT_CRITICAL();
+
+    /*
+     * Just record that this handler was called when the process was blocked.
+     * The handler will be called after sigsuspend() returns in the correct
+     * order.
+     */
+    if (suspended) {
+        sigaddset(&suspsigs, sig);
+    } else {
+        sim_switch_tasks();
+    }
+}
+
+/*
+ * Disable signals and enter a critical section.
+ *
+ * Returns 1 if signals were already blocked and 0 otherwise.
+ */
+os_sr_t
+sim_save_sr(void)
+{
+    int error;
+    sigset_t omask;
+
+    counter++;
+
+    error = sigprocmask(SIG_BLOCK, &allsigs, &omask);
+    assert(error == 0);
+
+    /*
+     * If any one of the signals in 'allsigs' is present in 'omask' then
+     * we are already inside a critical section.
+     */
+    return (sigismember(&omask, SIGURG));
+}
+
+void
+sim_restore_sr(os_sr_t osr)
+{
+    int error;
+
+    OS_ASSERT_CRITICAL();
+    assert(osr == 0 || osr == 1);
+
+    if (counter > 0) {
+        counter--;
+    }
+
+    if (osr == 1 || in_irq == 1 || counter > 0) {
+        /* Exiting a nested critical section */
+        return;
+    }
+
+    error = sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
+    assert(error == 0);
+}
+
+int
+sim_in_critical(void)
+{
+    int error;
+    sigset_t omask;
+
+    error = sigprocmask(SIG_SETMASK, NULL, &omask);
+    assert(error == 0);
+
+    /*
+     * If any one of the signals in 'allsigs' is present in 'omask' then
+     * we are already inside a critical section.
+     */
+    return (sigismember(&omask, SIGURG));
+}
+
+static struct {
+    int num;
+    void (*handler)(int sig);
+} signals[] = {
+//    { SIGALRM, timer_handler },
+    { SIGURG, ctxsw_handler },
+};
+
+#define NUMSIGS     (sizeof(signals)/sizeof(signals[0]))
+
+void
+sim_tick_idle(os_time_t ticks)
+{
+    int i, rc, sig;
+    struct itimerval it;
+    void (*handler)(int sig);
+
+    OS_ASSERT_CRITICAL();
+
+    if (ticks > 0) {
+        /*
+         * Enter tickless regime and set the timer to fire after 'ticks'
+         * worth of time has elapsed.
+         */
+        it.it_value.tv_sec = ticks / OS_TICKS_PER_SEC;
+        it.it_value.tv_usec = (ticks % OS_TICKS_PER_SEC) * OS_USEC_PER_TICK;
+        it.it_interval.tv_sec = 0;
+        it.it_interval.tv_usec = OS_USEC_PER_TICK;
+        rc = setitimer(ITIMER_REAL, &it, NULL);
+        assert(rc == 0);
+    }
+
+    suspended = true;
+    sigemptyset(&suspsigs);
+    sigsuspend(&nosigs);        /* Wait for a signal to wake us up */
+    suspended = false;
+
+    /*
+     * Call handlers for signals delivered to the process during sigsuspend().
+     * The SIGALRM handler is called before any other handlers to ensure that
+     * OS time is always correct.
+     */
+    if (sigismember(&suspsigs, SIGALRM)) {
+        sim_tick();
+    }
+    for (i = 0; i < NUMSIGS; i++) {
+        sig = signals[i].num;
+        handler = signals[i].handler;
+        if (sig != SIGALRM && sigismember(&suspsigs, sig)) {
+            handler(sig);
+        }
+    }
+
+    if (ticks > 0) {
+        /*
+         * Enable the periodic timer interrupt.
+         */
+        it.it_value.tv_sec = 0;
+        it.it_value.tv_usec = OS_USEC_PER_TICK;
+        it.it_interval.tv_sec = 0;
+        it.it_interval.tv_usec = OS_USEC_PER_TICK;
+        rc = setitimer(ITIMER_REAL, &it, NULL);
+        assert(rc == 0);
+    }
+}
+
+void
+sim_signals_init(void)
+{
+    int i, error;
+    struct sigaction sa;
+
+    sigemptyset(&nosigs);
+    sigemptyset(&allsigs);
+    for (i = 0; i < NUMSIGS; i++) {
+        sigaddset(&allsigs, signals[i].num);
+    }
+
+    for (i = 0; i < NUMSIGS; i++) {
+        memset(&sa, 0, sizeof sa);
+        sa.sa_handler = signals[i].handler;
+        sa.sa_mask = allsigs;
+        sa.sa_flags = SA_RESTART;
+        error = sigaction(signals[i].num, &sa, NULL);
+        assert(error == 0);
+    }
+
+    /*
+     * We use SIGALRM as a proxy for 'allsigs' to check if we are inside
+     * a critical section (for e.g. see sim_in_critical()). Make sure
+     * that SIGALRM is indeed present in 'allsigs'.
+     */
+//    assert(sigismember(&allsigs, SIGALRM));
+}
+
+void
+sim_signals_cleanup(void)
+{
+    int i, error;
+    struct sigaction sa;
+
+    for (i = 0; i < NUMSIGS; i++) {
+        memset(&sa, 0, sizeof sa);
+        sa.sa_handler = SIG_DFL;
+        error = sigaction(signals[i].num, &sa, NULL);
+        assert(error == 0);
+    }
+}
+
+#endif /* MYNEWT_VAL(MCU_NATIVE_USE_SIGNALS) */
diff --git a/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/startup_nrf52_bsim.c b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/startup_nrf52_bsim.c
new file mode 100644
index 0000000..d481068
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/src/arch/bsim_arch/startup_nrf52_bsim.c
@@ -0,0 +1,231 @@
+/*
+ * 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 "nrf.h"
+
+/**************************************************************************************************
+  Macros
+**************************************************************************************************/
+
+/*! Weak symbol reference. */
+#define WEAK        __attribute__ ((weak))
+
+/**************************************************************************************************
+  Functions
+**************************************************************************************************/
+
+extern void SystemInit(void);
+static void SystemDefaultHandler(void);
+
+/* Core vectors. */
+void WEAK Reset_Handler(void);
+void WEAK NMI_Handler(void);
+void WEAK HardFault_Handler(void);
+void WEAK MemoryManagement_Handler(void);
+void WEAK BusFault_Handler(void);
+void WEAK UsageFault_Handler(void);
+void WEAK SVC_Handler(void);
+void WEAK DebugMon_Handler(void);
+void WEAK PendSV_Handler(void);
+void WEAK SysTick_Handler(void);
+void WEAK POWER_CLOCK_IRQHandler(void);
+void WEAK RADIO_IRQHandler(void);
+void WEAK UARTE0_UART0_IRQHandler(void);
+void WEAK SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void);
+void WEAK SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void);
+void WEAK NFCT_IRQHandler(void);
+void WEAK GPIOTE_IRQHandler(void);
+void WEAK SAADC_IRQHandler(void);
+void WEAK TIMER0_IRQHandler(void);
+void WEAK TIMER1_IRQHandler(void);
+void WEAK TIMER2_IRQHandler(void);
+void WEAK RTC0_IRQHandler(void);
+void WEAK TEMP_IRQHandler(void);
+void WEAK RNG_IRQHandler(void);
+void WEAK ECB_IRQHandler(void);
+void WEAK CCM_AAR_IRQHandler(void);
+void WEAK WDT_IRQHandler(void);
+void WEAK RTC1_IRQHandler(void);
+void WEAK QDEC_IRQHandler(void);
+void WEAK COMP_LPCOMP_IRQHandler(void);
+void WEAK SWI0_EGU0_IRQHandler(void);
+void WEAK SWI1_EGU1_IRQHandler(void);
+void WEAK SWI2_EGU2_IRQHandler(void);
+void WEAK SWI3_EGU3_IRQHandler(void);
+void WEAK SWI4_EGU4_IRQHandler(void);
+void WEAK SWI5_EGU5_IRQHandler(void);
+void WEAK TIMER3_IRQHandler(void);
+void WEAK TIMER4_IRQHandler(void);
+void WEAK PWM0_IRQHandler(void);
+void WEAK PDM_IRQHandler(void);
+void WEAK MWU_IRQHandler(void);
+void WEAK PWM1_IRQHandler(void);
+void WEAK PWM2_IRQHandler(void);
+void WEAK SPIM2_SPIS2_SPI2_IRQHandler(void);
+void WEAK RTC2_IRQHandler(void);
+void WEAK I2S_IRQHandler(void);
+void WEAK FPU_IRQHandler(void);
+
+/* Assign default weak references. Override these values by defining a new function with the same name. */
+#pragma weak NMI_Handler                                    = SystemDefaultHandler
+#pragma weak HardFault_Handler                              = SystemDefaultHandler
+#pragma weak MemoryManagement_Handler                       = SystemDefaultHandler
+#pragma weak BusFault_Handler                               = SystemDefaultHandler
+#pragma weak UsageFault_Handler                             = SystemDefaultHandler
+#pragma weak SVC_Handler                                    = SystemDefaultHandler
+#pragma weak DebugMon_Handler                               = SystemDefaultHandler
+#pragma weak PendSV_Handler                                 = SystemDefaultHandler
+#pragma weak SysTick_Handler                                = SystemDefaultHandler
+#pragma weak POWER_CLOCK_IRQHandler                         = SystemDefaultHandler
+#pragma weak RADIO_IRQHandler                               = SystemDefaultHandler
+#pragma weak UARTE0_UART0_IRQHandler                        = SystemDefaultHandler
+#pragma weak SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler   = SystemDefaultHandler
+#pragma weak SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler   = SystemDefaultHandler
+#pragma weak NFCT_IRQHandler                                = SystemDefaultHandler
+#pragma weak GPIOTE_IRQHandler                              = SystemDefaultHandler
+#pragma weak SAADC_IRQHandler                               = SystemDefaultHandler
+#pragma weak TIMER0_IRQHandler                              = SystemDefaultHandler
+#pragma weak TIMER1_IRQHandler                              = SystemDefaultHandler
+#pragma weak TIMER2_IRQHandler                              = SystemDefaultHandler
+#pragma weak RTC0_IRQHandler                                = SystemDefaultHandler
+#pragma weak TEMP_IRQHandler                                = SystemDefaultHandler
+#pragma weak RNG_IRQHandler                                 = SystemDefaultHandler
+#pragma weak ECB_IRQHandler                                 = SystemDefaultHandler
+#pragma weak CCM_AAR_IRQHandler                             = SystemDefaultHandler
+#pragma weak WDT_IRQHandler                                 = SystemDefaultHandler
+#pragma weak RTC1_IRQHandler                                = SystemDefaultHandler
+#pragma weak QDEC_IRQHandler                                = SystemDefaultHandler
+#pragma weak COMP_LPCOMP_IRQHandler                         = SystemDefaultHandler
+#pragma weak SWI0_EGU0_IRQHandler                           = SystemDefaultHandler
+#pragma weak SWI1_EGU1_IRQHandler                           = SystemDefaultHandler
+#pragma weak SWI2_EGU2_IRQHandler                           = SystemDefaultHandler
+#pragma weak SWI3_EGU3_IRQHandler                           = SystemDefaultHandler
+#pragma weak SWI4_EGU4_IRQHandler                           = SystemDefaultHandler
+#pragma weak SWI5_EGU5_IRQHandler                           = SystemDefaultHandler
+#pragma weak TIMER3_IRQHandler                              = SystemDefaultHandler
+#pragma weak TIMER4_IRQHandler                              = SystemDefaultHandler
+#pragma weak PWM0_IRQHandler                                = SystemDefaultHandler
+#pragma weak PDM_IRQHandler                                 = SystemDefaultHandler
+#pragma weak MWU_IRQHandler                                 = SystemDefaultHandler
+#pragma weak PWM1_IRQHandler                                = SystemDefaultHandler
+#pragma weak PWM2_IRQHandler                                = SystemDefaultHandler
+#pragma weak SPIM2_SPIS2_SPI2_IRQHandler                    = SystemDefaultHandler
+#pragma weak RTC2_IRQHandler                                = SystemDefaultHandler
+#pragma weak I2S_IRQHandler                                 = SystemDefaultHandler
+#pragma weak FPU_IRQHandler                                 = SystemDefaultHandler
+
+/**************************************************************************************************
+  Global variables
+**************************************************************************************************/
+
+/*! Core vector table */
+void (* systemVectors[256])(void) =
+{
+  0,                                            /*  0: The initial stack pointer */
+  Reset_Handler,                                /*  1: The reset handler */
+  NMI_Handler,                                  /*  2: The NMI handler */
+  HardFault_Handler,                            /*  3: The hard fault handler */
+  MemoryManagement_Handler,                     /*  4: The MPU fault handler */
+  BusFault_Handler,                             /*  5: The bus fault handler */
+  UsageFault_Handler,                           /*  6: The usage fault handler */
+  0,                                            /*  7: Reserved */
+  0,                                            /*  8: Reserved */
+  0,                                            /*  9: Reserved */
+  0,                                            /* 10: Reserved */
+  SVC_Handler,                                  /* 11: SVCall handler */
+  DebugMon_Handler,                             /* 12: Debug monitor handler */
+  0,                                            /* 13: Reserved */
+  PendSV_Handler,                               /* 14: The PendSV handler */
+  SysTick_Handler,                              /* 15: The SysTick handler */
+
+  /* External interrupts */
+  POWER_CLOCK_IRQHandler,                       /* 16: POWER_CLOCK */
+  RADIO_IRQHandler,                             /* 17: RADIO */
+  UARTE0_UART0_IRQHandler,                      /* 18: UART0 */
+  SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler, /* 19: SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 */
+  SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler, /* 20: SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 */
+  NFCT_IRQHandler,                              /* 21: NFCT */
+  GPIOTE_IRQHandler,                            /* 22: GPIOTE */
+  SAADC_IRQHandler,                             /* 23: SAADC */
+  TIMER0_IRQHandler,                            /* 24: TIMER0 */
+  TIMER1_IRQHandler,                            /* 25: TIMER1 */
+  TIMER2_IRQHandler,                            /* 26: TIMER2 */
+  RTC0_IRQHandler,                              /* 27: RTC0 */
+  TEMP_IRQHandler,                              /* 28: TEMP */
+  RNG_IRQHandler,                               /* 29: RNG */
+  ECB_IRQHandler,                               /* 30: ECB */
+  CCM_AAR_IRQHandler,                           /* 31: CCM_AAR */
+  WDT_IRQHandler,                               /* 32: WDT */
+  RTC1_IRQHandler,                              /* 33: RTC1 */
+  QDEC_IRQHandler,                              /* 34: QDEC */
+  COMP_LPCOMP_IRQHandler,                       /* 35: COMP_LPCOMP */
+  SWI0_EGU0_IRQHandler,                         /* 36: SWI0_EGU0 */
+  SWI1_EGU1_IRQHandler,                         /* 37: SWI1_EGU1 */
+  SWI2_EGU2_IRQHandler,                         /* 38: SWI2_EGU2 */
+  SWI3_EGU3_IRQHandler,                         /* 39: SWI3_EGU3 */
+  SWI4_EGU4_IRQHandler,                         /* 40: SWI4_EGU4 */
+  SWI5_EGU5_IRQHandler,                         /* 41: SWI5_EGU5 */
+  TIMER3_IRQHandler,                            /* 42: TIMER3 */
+  TIMER4_IRQHandler,                            /* 43: TIMER4 */
+  PWM0_IRQHandler,                              /* 44: PWM0 */
+  PDM_IRQHandler,                               /* 45: PDM */
+  0,                                            /* 46: Reserved */
+  0,                                            /* 47: Reserved */
+  MWU_IRQHandler,                               /* 48: MWU */
+  PWM1_IRQHandler,                              /* 49: PWM1 */
+  PWM2_IRQHandler,                              /* 50: PWM2 */
+  SPIM2_SPIS2_SPI2_IRQHandler,                  /* 51: SPIM2_SPIS2_SPI2 */
+  RTC2_IRQHandler,                              /* 52: RTC2 */
+  I2S_IRQHandler,                               /* 53: I2S */
+  FPU_IRQHandler,                               /* 54: FPU */
+  0,                                            /* 55: Reserved */
+  0,                                            /* 56: Reserved */
+  0,                                            /* 57: Reserved */
+  0,                                            /* 58: Reserved */
+  0,                                            /* 59: Reserved */
+  0,                                            /* 60: Reserved */
+  0,                                            /* 61: Reserved */
+  0,                                            /* 62: Reserved */
+  0                                             /* 63: Reserved */
+                                                /* 64..127: Reserved */
+};
+
+/*************************************************************************************************/
+/*!
+ *  \brief      Reset handler.
+ */
+/*************************************************************************************************/
+void Reset_Handler(void)
+{
+  /* Core initialization. */
+  SystemInit();
+}
+
+/*************************************************************************************************/
+/*!
+ *  \brief      Default vector handler.
+ *
+ *  \param      None.
+ */
+/*************************************************************************************************/
+static void SystemDefaultHandler(void)
+{
+  volatile unsigned int forever = 1;
+  while (forever);
+}
diff --git a/babblesim/hw/bsp/nrf52_bsim/src/hal_bsp.c b/babblesim/hw/bsp/nrf52_bsim/src/hal_bsp.c
new file mode 100644
index 0000000..4250249
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/src/hal_bsp.c
@@ -0,0 +1,175 @@
+/*
+ * 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 <stdint.h>
+#include <stddef.h>
+#include <assert.h>
+#include "os/mynewt.h"
+#include "nrfx.h"
+#include "flash_map/flash_map.h"
+#include "hal/hal_bsp.h"
+#include "hal/hal_flash.h"
+#include "hal/hal_system.h"
+#include "mcu/nrf52_hal.h"
+#include "mcu/nrf52_periph.h"
+#include "bsp/bsp.h"
+#include "defs/sections.h"
+#include "uart_hal/uart_hal.h"
+#include "uart/uart.h"
+#if MYNEWT_VAL(ENC_FLASH_DEV)
+#include <ef_nrf5x/ef_nrf5x.h>
+#endif
+
+/*
+ * What memory to include in coredump.
+ */
+static const struct hal_bsp_mem_dump dump_cfg[] = {
+    [0] = {
+        .hbmd_start = &_ram_start,
+        .hbmd_size = RAM_SIZE
+    }
+};
+
+#if MYNEWT_VAL(ENC_FLASH_DEV)
+static sec_data_secret struct eflash_nrf5x_dev enc_flash_dev0 = {
+    .end_dev = {
+        .efd_hal = {
+            .hf_itf = &enc_flash_funcs,
+        },
+        .efd_hwdev = &nrf52k_flash_dev
+    }
+};
+#endif
+
+const struct hal_flash *
+hal_bsp_flash_dev(uint8_t id)
+{
+//    /*
+//     * Internal flash mapped to id 0.
+//     */
+//    if (id == 0) {
+//        return &nrf52k_flash_dev;
+//    }
+//#if MYNEWT_VAL(ENC_FLASH_DEV)
+//    if (id == 1) {
+//        return &enc_flash_dev0.end_dev.efd_hal;
+//    }
+//#endif
+    return NULL;
+}
+
+const struct hal_bsp_mem_dump *
+hal_bsp_core_dump(int *area_cnt)
+{
+    *area_cnt = sizeof(dump_cfg) / sizeof(dump_cfg[0]);
+    return dump_cfg;
+}
+
+int
+hal_bsp_power_state(int state)
+{
+    return (0);
+}
+
+/**
+ * Returns the configured priority for the given interrupt. If no priority
+ * configured, return the priority passed in
+ *
+ * @param irq_num
+ * @param pri
+ *
+ * @return uint32_t
+ */
+uint32_t
+hal_bsp_get_nvic_priority(int irq_num, uint32_t pri)
+{
+    uint32_t cfg_pri;
+
+    switch (irq_num) {
+    /* Radio gets highest priority */
+    case RADIO_IRQn:
+        cfg_pri = 0;
+        break;
+    default:
+        cfg_pri = pri;
+    }
+    return cfg_pri;
+}
+
+static void
+nrf52_periph_create_timers(void)
+{
+    int rc;
+
+    (void)rc;
+
+#if MYNEWT_VAL(TIMER_0)
+    rc = hal_timer_init(0, NULL);
+    assert(rc == 0);
+#endif
+#if MYNEWT_VAL(TIMER_1)
+    rc = hal_timer_init(1, NULL);
+    assert(rc == 0);
+#endif
+#if MYNEWT_VAL(TIMER_2)
+    rc = hal_timer_init(2, NULL);
+    assert(rc == 0);
+#endif
+#if MYNEWT_VAL(TIMER_3)
+    rc = hal_timer_init(3, NULL);
+    assert(rc == 0);
+#endif
+#if MYNEWT_VAL(TIMER_4)
+    rc = hal_timer_init(4, NULL);
+    assert(rc == 0);
+#endif
+#if MYNEWT_VAL(TIMER_5)
+    rc = hal_timer_init(5, NULL);
+    assert(rc == 0);
+#endif
+
+#if MYNEWT_VAL(OS_CPUTIME_TIMER_NUM) >= 0
+    rc = os_cputime_init(MYNEWT_VAL(OS_CPUTIME_FREQ));
+    assert(rc == 0);
+#endif
+}
+
+static struct uart_dev os_bsp_uart0;
+
+void
+hal_bsp_init(void)
+{
+    /* Make sure system clocks have started */
+    hal_system_clock_start();
+
+    /* Create all available nRF52840 peripherals */
+//    nrf52_periph_create();
+    nrf52_periph_create_timers();
+
+    int rc;
+
+    rc = os_dev_create((struct os_dev *) &os_bsp_uart0, "uart0",
+                       OS_DEV_INIT_PRIMARY, 0, uart_hal_init, (void *) NULL);
+    assert(rc == 0);
+}
+
+void
+hal_bsp_deinit(void)
+{
+}
diff --git a/babblesim/hw/bsp/nrf52_bsim/src/sbrk.c b/babblesim/hw/bsp/nrf52_bsim/src/sbrk.c
new file mode 100644
index 0000000..5df43c9
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/src/sbrk.c
@@ -0,0 +1,59 @@
+/*
+ * 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 <hal/hal_bsp.h>
+
+/* put these in the data section so they are not cleared by _start */
+static char *sbrkBase __attribute__ ((section (".data")));
+static char *sbrkLimit __attribute__ ((section (".data")));
+static char *brk __attribute__ ((section (".data")));
+
+void
+_sbrkInit(char *base, char *limit) {
+    sbrkBase = base;
+    sbrkLimit = limit;
+    brk = base;
+}
+
+void *
+_sbrk(int incr)
+{
+    void *prev_brk;
+
+    if (incr < 0) {
+        /* Returning memory to the heap. */
+        incr = -incr;
+        if (brk - incr < sbrkBase) {
+            prev_brk = (void *)-1;
+        } else {
+            prev_brk = brk;
+            brk -= incr;
+        }
+    } else {
+        /* Allocating memory from the heap. */
+        if (sbrkLimit - brk >= incr) {
+            prev_brk = brk;
+            brk += incr;
+        } else {
+            prev_brk = (void *)-1;
+        }
+    }
+
+    return prev_brk;
+}
diff --git a/babblesim/hw/bsp/nrf52_bsim/syscfg.yml b/babblesim/hw/bsp/nrf52_bsim/syscfg.yml
new file mode 100644
index 0000000..0e9eb60
--- /dev/null
+++ b/babblesim/hw/bsp/nrf52_bsim/syscfg.yml
@@ -0,0 +1,73 @@
+# 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.
+#
+
+syscfg.defs:
+    BSP_NRF52:
+        description: 'Set to indicate that BSP has NRF52'
+        value: 1
+    SOFT_PWM:
+        description: 'Enable soft PWM'
+        value: 0
+    ENC_FLASH_DEV:
+        description: 'Encrypting flash driver over interal flash for testing'
+        value: 0
+    UARTBB_0:
+        description: 'Enable bit-banger UART 0'
+        value: 0
+    RAM_RESIDENT:
+        description: 'Compile app to be loaded to RAM'
+        value: 0
+
+syscfg.vals:
+    OS_MAIN_STACK_SIZE: 8000
+    BLE_HCI_TRANSPORT: uart
+    MCU_TIMER_POLLER_PRIO: 0
+    BLE_LL_PRIO: 1
+    MCU_UART_POLLER_PRIO: 2
+
+    # Enable nRF52832 MCU
+    MCU_TARGET: nRF52832
+    # Set default pins for peripherals
+    UART_0_PIN_TX: 6
+    UART_0_PIN_RX: 8
+    UART_0_PIN_RTS: 5
+    UART_0_PIN_CTS: 7
+    SPI_0_MASTER_PIN_SCK: 23
+    SPI_0_MASTER_PIN_MOSI: 24
+    SPI_0_MASTER_PIN_MISO: 25
+    SPI_0_SLAVE_PIN_SCK: 23
+    SPI_0_SLAVE_PIN_MOSI: 24
+    SPI_0_SLAVE_PIN_MISO: 25
+    SPI_0_SLAVE_PIN_SS: 22
+    I2C_0_PIN_SCL: 27
+    I2C_0_PIN_SDA: 26
+
+    CONFIG_FCB_FLASH_AREA: FLASH_AREA_NFFS
+    REBOOT_LOG_FLASH_AREA: FLASH_AREA_REBOOT_LOG
+    NFFS_FLASH_AREA: FLASH_AREA_NFFS
+    COREDUMP_FLASH_AREA: FLASH_AREA_IMAGE_1
+    MCU_DCDC_ENABLED: 1
+    MCU_LFCLK_SOURCE: LFXO
+    BOOT_SERIAL_DETECT_PIN: 13  # Button 1
+
+syscfg.vals.BLE_CONTROLLER:
+    TIMER_0: 0
+    TIMER_5: 1
+    OS_CPUTIME_FREQ: 32768
+    OS_CPUTIME_TIMER_NUM: 5
+    BLE_LL_RFMGMT_ENABLE_TIME: 1500
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/cmsis_nvic.h b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/cmsis_nvic.h
new file mode 100644
index 0000000..11a812d
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/cmsis_nvic.h
@@ -0,0 +1,28 @@
+/* mbed Microcontroller Library - cmsis_nvic
+ * Copyright (c) 2009-2011 ARM Limited. All rights reserved.
+ *
+ * CMSIS-style functionality to support dynamic vectors
+ */
+
+#ifndef MBED_CMSIS_NVIC_H
+#define MBED_CMSIS_NVIC_H
+
+#include <stdint.h>
+#include "nrf.h"
+
+#define NVIC_NUM_VECTORS      (16 + 38)   // CORE + MCU Peripherals
+#define NVIC_USER_IRQ_OFFSET  16
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void NVIC_Relocate(void);
+void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector);
+uint32_t NVIC_GetVector(IRQn_Type IRQn);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/cortex_m4.h b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/cortex_m4.h
new file mode 100644
index 0000000..93f2044
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/cortex_m4.h
@@ -0,0 +1,34 @@
+/*
+ * 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 __MCU_CORTEX_M4_H__
+#define __MCU_CORTEX_M4_H__
+
+#include "nrf.h"
+#include <syscfg/syscfg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCU_CORTEX_M4_H__ */
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/mcu.h b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/mcu.h
new file mode 100644
index 0000000..1950c85
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/mcu.h
@@ -0,0 +1,69 @@
+/*
+ * 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 __MCU_MCU_H_
+#define __MCU_MCU_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Defines for naming GPIOs. NOTE: the nordic chip docs use numeric labels for
+ * ports. Port A corresponds to Port 0, B to 1, etc. The nrf52832 has only one
+ * port and thus uses pins 0 - 31. The nrf52840 has two ports but Port 1 only
+ * has 16 pins.
+ */
+#define MCU_GPIO_PORTA(pin)	((0 * 16) + (pin))
+#define MCU_GPIO_PORTB(pin)	((1 * 16) + (pin))
+
+#if NRF52
+
+#define MCU_SYSVIEW_INTERRUPTS \
+    "I#1=Reset,I#2=MNI,I#3=HardFault,I#4=MemoryMgmt,I#5=BusFault,I#6=UsageFault," \
+    "I#11=SVCall,I#12=DebugMonitor,I#14=PendSV,I#15=SysTick," \
+    "I#16=POWER_CLOCK,I#17=RADIO,I#18=UARTE0_UART0,I#19=SPIx0_TWIx0," \
+    "I#20=SPIx1_TWIx1,I#21=NFCT,I#22=GPIOTE,I#23=SAADC," \
+    "I#24=TIMER0,I#25=TIMER1,I#26=TIMER2,I#27=RTC0,I#28=TEMP,I#29=RNG,I#30=ECB," \
+    "I#31=CCM_AAR,I#32=WDT,I#33=RTC1,I#34=QDEC,I#35=COMP_LPCOMP,I#36=SWI0_EGU0," \
+    "I#37=SWI1_EGU1,I#38=SWI2_EGU2,I#39=SWI3_EGU3,I#40=SWI4_EGU4,I#41=SWI5_EGU5," \
+    "I#42=TIMER3,I#43=TIMER4,I#44=PWM0,I#45=PDM,I#48=MWU,I#49=PWM1,I#50=PWM2," \
+    "I#51=SPIx2,I#52=RTC2,I#53=I2S,I#54=FPU"
+
+#elif NRF52840_XXAA
+
+#define MCU_SYSVIEW_INTERRUPTS \
+    "I#1=Reset,I#2=MNI,I#3=HardFault,I#4=MemoryMgmt,I#5=BusFault,I#6=UsageFault," \
+    "I#11=SVCall,I#12=DebugMonitor,I#14=PendSV,I#15=SysTick," \
+    "I#16=POWER_CLOCK,I#17=RADIO,I#18=UARTE0_UART0,I#19=SPIx0_TWIx0," \
+    "I#20=SPIx1_TWIx1,I#21=NFCT,I#22=GPIOTE,I#23=SAADC," \
+    "I#24=TIMER0,I#25=TIMER1,I#26=TIMER2,I#27=RTC0,I#28=TEMP,I#29=RNG,I#30=ECB," \
+    "I#31=CCM_AAR,I#32=WDT,I#33=RTC1,I#34=QDEC,I#35=COMP_LPCOMP,I#36=SWI0_EGU0," \
+    "I#37=SWI1_EGU1,I#38=SWI2_EGU2,I#39=SWI3_EGU3,I#40=SWI4_EGU4,I#41=SWI5_EGU5," \
+    "I#42=TIMER3,I#43=TIMER4,I#44=PWM0,I#45=PDM,I#48=MWU,I#49=PWM1,I#50=PWM2," \
+    "I#51=SPIx2,I#52=RTC2,I#53=I2S,I#54=FPU,I#55=USBD," \
+    "I#56=UARTE1,I#57=QSPI,I#58=CRYPTOCELL,I#61=PWM3,I#63=SPIM3"
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCU_MCU_H_ */
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/mcu_sim.h b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/mcu_sim.h
new file mode 100644
index 0000000..26f6cb9
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/mcu_sim.h
@@ -0,0 +1,38 @@
+/*
+ * 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 __MCU_SIM_H__
+#define __MCU_SIM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *native_flash_file;
+extern char *native_uart_log_file;
+extern const char *native_uart_dev_strs[];
+
+void mcu_sim_parse_args(int argc, char **argv);
+
+void static inline hal_debug_break(void) {}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCU_SIM_H__ */
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/nrf52_clock.h b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/nrf52_clock.h
new file mode 100644
index 0000000..d86aa98
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/nrf52_clock.h
@@ -0,0 +1,50 @@
+/*
+ * 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_NRF52_CLOCK_
+#define H_NRF52_CLOCK_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ * Request HFXO clock be turned on. Note that each request must have a
+ * corresponding release.
+ *
+ * @return int 0: hfxo was already on. 1: hfxo was turned on.
+ */
+int nrf52_clock_hfxo_request(void);
+
+/**
+ * Release the HFXO; caller no longer needs the HFXO to be turned on. Each call
+ * to release should have been preceeded by a corresponding call to request the
+ * HFXO
+ *
+ *
+ * @return int 0: HFXO not stopped by this call (others using it) 1: HFXO
+ *         stopped.
+ */
+int nrf52_clock_hfxo_release(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* H_NRF52_CLOCK_ */
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/nrf52_hal.h b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/nrf52_hal.h
new file mode 100644
index 0000000..df9a016
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/nrf52_hal.h
@@ -0,0 +1,101 @@
+/*
+ * 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_NRF52_HAL_
+#define H_NRF52_HAL_
+
+#include "cmsis.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Helper functions to enable/disable interrupts. */
+#define __HAL_DISABLE_INTERRUPTS(x)                     \
+    do {                                                \
+        x = __get_PRIMASK();                            \
+        __disable_irq();                                \
+    } while(0);
+
+#define __HAL_ENABLE_INTERRUPTS(x)                      \
+    do {                                                \
+        if (!x) {                                       \
+            __enable_irq();                             \
+        }                                               \
+    } while(0);
+
+struct nrf52_uart_cfg {
+    int8_t suc_pin_tx;                          /* pins for IO */
+    int8_t suc_pin_rx;
+    int8_t suc_pin_rts;
+    int8_t suc_pin_cts;
+};
+const struct nrf52_uart_cfg *bsp_uart_config(void);
+
+struct nrf52_hal_i2c_cfg {
+    int scl_pin;
+    int sda_pin;
+    uint32_t i2c_frequency;
+};
+struct hal_flash;
+extern const struct hal_flash nrf52k_flash_dev;
+extern const struct hal_flash nrf52k_qspi_dev;
+
+/* SPI configuration (used for both master and slave) */
+struct nrf52_hal_spi_cfg {
+    uint8_t sck_pin;
+    uint8_t mosi_pin;
+    uint8_t miso_pin;
+    uint8_t ss_pin;
+};
+
+/*
+ * GPIO pin mapping
+ *
+ * The logical GPIO pin numbers (0 to N) are mapped to ports in the following
+ * manner:
+ *  pins 0 - 31: Port 0
+ *  pins 32 - 48: Port 1.
+ *
+ *  The nrf52832 has only one port with 32 pins. The nrf52840 has 48 pins and
+ *  uses two ports.
+ *
+ *  NOTE: in order to save code space, there is no checking done to see if the
+ *  user specifies a pin that is not used by the processor. If an invalid pin
+ *  number is used unexpected and/or erroneous behavior will result.
+ */
+#if defined(NRF52832_XXAA) || defined(NRF52810_XXAA) || defined(NRF52811_XXAA)
+#define HAL_GPIO_INDEX(pin)     (pin)
+#define HAL_GPIO_PORT(pin)      (NRF_P0)
+#define HAL_GPIO_MASK(pin)      (1 << pin)
+#define HAL_GPIOTE_PIN_MASK     GPIOTE_CONFIG_PSEL_Msk
+#endif
+
+#ifdef NRF52840_XXAA
+#define HAL_GPIO_INDEX(pin)     ((pin) & 0x1F)
+#define HAL_GPIO_PORT(pin)      ((pin) > 31 ? NRF_P1 : NRF_P0)
+#define HAL_GPIO_MASK(pin)      (1 << HAL_GPIO_INDEX(pin))
+#define HAL_GPIOTE_PIN_MASK     (0x3FUL << GPIOTE_CONFIG_PSEL_Pos)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* H_NRF52_HAL_ */
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/nrf52_periph.h b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/nrf52_periph.h
new file mode 100644
index 0000000..0e49371
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/nrf52_periph.h
@@ -0,0 +1,33 @@
+/*
+ * 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_NRF52_PERIPH_
+#define H_NRF52_PERIPH_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+void nrf52_periph_create(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* H_NRF52_PERIPH_ */
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/pkg.yml b/babblesim/hw/mcu/nordic/nrf52_bsim/pkg.yml
new file mode 100644
index 0000000..4f332ac
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/pkg.yml
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+
+pkg.name: babblesim/hw/mcu/nordic/nrf52_bsim
+pkg.description: nRF52 on BabbleSim
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+
+pkg.deps:
+    - "babblesim/nrfx"
+
+pkg.deps.BLE_CONTROLLER:
+    - "@apache-mynewt-nimble/nimble/drivers/nrf52"
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_os_tick.c b/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_os_tick.c
new file mode 100644
index 0000000..a2d7170
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_os_tick.c
@@ -0,0 +1,226 @@
+/*
+ * 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 <assert.h>
+#include "os/mynewt.h"
+#include "hal/hal_os_tick.h"
+#include "nrf.h"
+#include "mcu/cmsis_nvic.h"
+#include "mcu/mcu_sim.h"
+#include <time_machine.h>
+#include <NRF_HWLowL.h>
+#include <NRF_HW_model_top.h>
+#include <NRF_RTC.h>
+#include <hal/nrf_rtc.h>
+
+/* The OS scheduler requires a low-frequency timer. */
+#if MYNEWT_VAL(OS_SCHEDULING) && !MYNEWT_VAL(MCU_LFCLK_SOURCE)
+    #error The OS scheduler requires a low-frequency timer; configure MCU_LFCLK_SOURCE
+#endif
+
+#define RTC_FREQ            32768       /* in Hz */
+#define OS_TICK_TIMER       NRF_RTC1
+#define OS_TICK_IRQ         RTC1_IRQn
+#define OS_TICK_CMPREG      3   /* generate timer interrupt */
+#define RTC_COMPARE_INT_MASK(ccreg) (1UL << ((ccreg) + 16))
+
+struct hal_os_tick
+{
+    int ticks_per_ostick;
+    os_time_t max_idle_ticks;
+    uint32_t lastocmp;
+};
+
+struct hal_os_tick g_hal_os_tick;
+
+/*
+ * Implement (x - y) where the range of both 'x' and 'y' is limited to 24-bits.
+ *
+ * For example:
+ *
+ * sub24(0, 0xffffff) = 1
+ * sub24(0xffffff, 0xfffffe) = 1
+ * sub24(0xffffff, 0) = -1
+ * sub24(0x7fffff, 0) = 8388607
+ * sub24(0x800000, 0) = -8388608
+ */
+static inline int
+sub24(uint32_t x, uint32_t y)
+{
+    int result;
+
+    assert(x <= 0xffffff);
+    assert(y <= 0xffffff);
+
+    result = x - y;
+    if (result & 0x800000) {
+        return (result | 0xff800000);
+    } else {
+        return (result & 0x007fffff);
+    }
+}
+
+static inline uint32_t
+nrf52_os_tick_counter(void)
+{
+    return nrf_rtc_counter_get(OS_TICK_TIMER);
+}
+
+static inline void
+nrf52_os_tick_set_ocmp(uint32_t ocmp)
+{
+    int delta;
+    uint32_t counter;
+
+    OS_ASSERT_CRITICAL();
+    while (1) {
+        ocmp &= 0xffffff;
+        nrf_rtc_cc_set(OS_TICK_TIMER, OS_TICK_CMPREG, ocmp);
+        counter = nrf52_os_tick_counter();
+        /*
+         * From nRF52 Product specification
+         *
+         * - If Counter is 'N' writing (N) or (N + 1) to CC register
+         *   may not trigger a compare event.
+         *
+         * - If Counter is 'N' writing (N + 2) to CC register is guaranteed
+         *   to trigger a compare event at 'N + 2'.
+         */
+        delta = sub24(ocmp, counter);
+        if (delta > 2) {
+            break;
+        }
+        ocmp += g_hal_os_tick.ticks_per_ostick;
+    }
+}
+
+static void
+nrf52_timer_handler(void)
+{
+    int delta;
+    int ticks;
+    os_sr_t sr;
+    uint32_t counter;
+
+    os_trace_isr_enter();
+    OS_ENTER_CRITICAL(sr);
+
+    /* Calculate elapsed ticks and advance OS time. */
+
+    counter = nrf52_os_tick_counter();
+    delta = sub24(counter, g_hal_os_tick.lastocmp);
+    ticks = delta / g_hal_os_tick.ticks_per_ostick;
+    os_time_advance(ticks);
+
+    /* Clear timer interrupt */
+    OS_TICK_TIMER->EVENTS_COMPARE[OS_TICK_CMPREG] = 0;
+
+    /* Update the time associated with the most recent tick */
+    g_hal_os_tick.lastocmp = (g_hal_os_tick.lastocmp +
+        (ticks * g_hal_os_tick.ticks_per_ostick)) & 0xffffff;
+
+    /* Update the output compare to interrupt at the next tick */
+    nrf52_os_tick_set_ocmp(g_hal_os_tick.lastocmp + g_hal_os_tick.ticks_per_ostick);
+
+    OS_EXIT_CRITICAL(sr);
+    os_trace_isr_exit();
+}
+
+/* Wait For Interrupt */
+void
+__WFI(void)
+{
+    while (hw_irq_ctrl_get_irq_status() == 0) {
+        tm_tick();
+    }
+}
+
+void
+os_tick_idle(os_time_t ticks)
+{
+    uint32_t ocmp;
+
+    OS_ASSERT_CRITICAL();
+
+    if (ticks > 0) {
+        /*
+         * Enter tickless regime during long idle durations.
+         */
+        if (ticks > g_hal_os_tick.max_idle_ticks) {
+            ticks = g_hal_os_tick.max_idle_ticks;
+        }
+        ocmp = g_hal_os_tick.lastocmp + (ticks*g_hal_os_tick.ticks_per_ostick);
+        nrf52_os_tick_set_ocmp(ocmp);
+    }
+
+    __WFI();
+
+    if (ticks > 0) {
+        /*
+         * Update OS time before anything else when coming out of
+         * the tickless regime.
+         */
+        nrf52_timer_handler();
+    }
+}
+
+extern void nrf_rtc_regw_sideeffects(int i);
+
+void
+os_tick_init(uint32_t os_ticks_per_sec, int prio)
+{
+    uint32_t sr;
+
+    assert(RTC_FREQ % os_ticks_per_sec == 0);
+
+    g_hal_os_tick.lastocmp = 0;
+    g_hal_os_tick.ticks_per_ostick = RTC_FREQ / os_ticks_per_sec;
+
+    /*
+     * The maximum number of OS ticks allowed to elapse during idle is
+     * limited to 1/4th the number of timer ticks before the 24-bit counter
+     * rolls over.
+     */
+    g_hal_os_tick.max_idle_ticks = (1UL << 22) / g_hal_os_tick.ticks_per_ostick;
+
+    /* disable interrupts */
+    OS_ENTER_CRITICAL(sr);
+
+    /* Set isr in vector table and enable interrupt */
+    NVIC_SetPriority(OS_TICK_IRQ, prio);
+    NVIC_SetVector(OS_TICK_IRQ, (uint32_t)nrf52_timer_handler);
+    NVIC_EnableIRQ(OS_TICK_IRQ);
+
+    /*
+     * Program the OS_TICK_TIMER to operate at 32KHz and trigger an output
+     * compare interrupt at a rate of 'os_ticks_per_sec'.
+     */
+    nrf_rtc_task_trigger(OS_TICK_TIMER, NRF_RTC_TASK_STOP);
+    nrf_rtc_task_trigger(OS_TICK_TIMER, NRF_RTC_TASK_CLEAR);
+    nrf_rtc_event_disable(OS_TICK_TIMER, 0xffffffff);
+    nrf_rtc_int_disable(OS_TICK_TIMER, 0xffffffff);
+    nrf_rtc_int_enable(OS_TICK_TIMER, RTC_COMPARE_INT_MASK(OS_TICK_CMPREG));
+
+    OS_TICK_TIMER->EVENTS_COMPARE[OS_TICK_CMPREG] = 0;
+    nrf_rtc_cc_set(OS_TICK_TIMER, OS_TICK_CMPREG, g_hal_os_tick.ticks_per_ostick);
+
+    nrf_rtc_task_trigger(OS_TICK_TIMER, NRF_RTC_TASK_START);
+
+    OS_EXIT_CRITICAL(sr);
+}
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_reset_cause.c b/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_reset_cause.c
new file mode 100644
index 0000000..32182c1
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_reset_cause.c
@@ -0,0 +1,47 @@
+/*
+ * 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 <nrf.h>
+#include "hal/hal_system.h"
+
+enum hal_reset_reason
+hal_reset_cause(void)
+{
+    static enum hal_reset_reason reason;
+    uint32_t reg;
+
+    if (reason) {
+        return reason;
+    }
+    reg = NRF_POWER->RESETREAS;
+
+    if (reg & (POWER_RESETREAS_DOG_Msk | POWER_RESETREAS_LOCKUP_Msk)) {
+        reason = HAL_RESET_WATCHDOG;
+    } else if (reg & POWER_RESETREAS_SREQ_Msk) {
+        reason = HAL_RESET_SOFT;
+    } else if (reg & POWER_RESETREAS_RESETPIN_Msk) {
+        reason = HAL_RESET_PIN;
+    } else if (reg & POWER_RESETREAS_OFF_Msk) {
+        reason = HAL_RESET_SYS_OFF_INT;
+    } else {
+        reason = HAL_RESET_POR; /* could also be brownout */
+    }
+    NRF_POWER->RESETREAS = reg;
+    return reason;
+}
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_system.c b/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_system.c
new file mode 100644
index 0000000..4f46f34
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_system.c
@@ -0,0 +1,128 @@
+/*
+ * 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 "syscfg/syscfg.h"
+#include "hal/hal_system.h"
+#include "hal/hal_debug.h"
+#include "nrf.h"
+#include "cmsis.h"
+#include "mcu/mcu_sim.h"
+#include "hal/nrf_clock.h"
+
+/**
+ * Function called at startup. Called after BSS and .data initialized but
+ * prior to the _start function.
+ *
+ * NOTE: this function is called by both the bootloader and the application.
+ * If you add code here that you do not want executed in either case you need
+ * to conditionally compile it using the config variable BOOT_LOADER (will
+ * be set to 1 in case of bootloader build)
+ *
+ */
+void
+hal_system_init(void)
+{
+#if MYNEWT_VAL(MCU_DCDC_ENABLED)
+    NRF_POWER->DCDCEN = 1;
+#endif
+}
+
+void
+hal_system_reset(void)
+{
+
+#if MYNEWT_VAL(HAL_SYSTEM_RESET_CB)
+    hal_system_reset_cb();
+#endif
+
+    while (1) {
+        HAL_DEBUG_BREAK();
+        NVIC_SystemReset();
+    }
+}
+
+int
+hal_debugger_connected(void)
+{
+    return 0;
+}
+
+/**
+ * hal system clock start
+ *
+ * Makes sure the LFCLK and/or HFCLK is started.
+ */
+void
+hal_system_clock_start(void)
+{
+#if MYNEWT_VAL(MCU_LFCLK_SOURCE)
+    uint32_t regmsk;
+    uint32_t regval;
+    uint32_t clksrc;
+
+    regmsk = CLOCK_LFCLKSTAT_STATE_Msk | CLOCK_LFCLKSTAT_SRC_Msk;
+    regval = CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos;
+
+#if MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFXO)
+    regval |= CLOCK_LFCLKSTAT_SRC_Xtal << CLOCK_LFCLKSTAT_SRC_Pos;
+    clksrc = CLOCK_LFCLKSRC_SRC_Xtal;
+#elif MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFSYNTH)
+    regval |= CLOCK_LFCLKSTAT_SRC_Synth << CLOCK_LFCLKSTAT_SRC_Pos;
+    clksrc = CLOCK_LFCLKSRC_SRC_Synth;
+#elif MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFRC)
+    regval |= CLOCK_LFCLKSTAT_SRC_RC << CLOCK_LFCLKSTAT_SRC_Pos;
+    clksrc = CLOCK_LFCLKSRC_SRC_RC;
+#else
+    #error Unknown LFCLK source selected
+#endif
+
+#if MYNEWT_VAL_CHOICE(MCU_LFCLK_SOURCE, LFSYNTH)
+    /* Must turn on HFLCK for synthesized 32768 crystal */
+    nrf52_clock_hfxo_request();
+#else
+    /* Make sure HFCLK is stopped */
+    nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTOP);
+#endif
+
+    /* Check if this clock source is already running */
+    if ((NRF_CLOCK_regs.LFCLKSTAT & regmsk) != regval) {
+
+        nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTOP);
+        NRF_CLOCK_regs.EVENTS_LFCLKSTARTED = 0;
+        NRF_CLOCK_regs.LFCLKSRC = clksrc;
+        nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTART);
+
+        /* Wait here till started! */
+//        while (1) {
+//            if (NRF_CLOCK_regs.EVENTS_LFCLKSTARTED) {
+//                if ((NRF_CLOCK_regs.LFCLKSTAT & regmsk) == regval) {
+//                    break;
+//                }
+//            }
+//        }
+    }
+#endif
+}
+
+
+void*
+NRF_RADIO_BASE_FUN(void)
+{
+    return NULL;
+}
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_timer.c b/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_timer.c
new file mode 100644
index 0000000..0e3d914
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_timer.c
@@ -0,0 +1,949 @@
+/*
+ * 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 <hal/nrf_rtc.h>
+#include "os/mynewt.h"
+#include "mcu/cmsis_nvic.h"
+#include "hal/hal_timer.h"
+#include "nrf.h"
+#include "mcu/nrf52_hal.h"
+#include "mcu/nrf52_clock.h"
+#include "hal/nrf_timer.h"
+
+/* IRQ prototype */
+typedef void (*hal_timer_irq_handler_t)(void);
+
+/* User CC 2 for reading counter, CC 3 for timer isr */
+#define NRF_TIMER_CC_READ       (NRF_TIMER_CC_CHANNEL2)
+#define NRF_TIMER_CC_INT        (3)
+
+/* Output compare 2 used for RTC timers */
+#define NRF_RTC_TIMER_CC_INT    (2)
+
+/* Maximum number of hal timers used */
+#define NRF52_HAL_TIMER_MAX     (6)
+
+/* Maximum timer frequency */
+#define NRF52_MAX_TIMER_FREQ    (16000000)
+
+struct nrf52_hal_timer {
+    uint8_t tmr_enabled;
+    uint8_t tmr_irq_num;
+    uint8_t tmr_rtc;
+    uint8_t tmr_pad;
+    uint32_t tmr_cntr;
+    uint32_t timer_isrs;
+    uint32_t tmr_freq;
+    void *tmr_reg;
+    TAILQ_HEAD(hal_timer_qhead, hal_timer) hal_timer_q;
+};
+
+#if MYNEWT_VAL(TIMER_0)
+struct nrf52_hal_timer nrf52_hal_timer0;
+#endif
+#if MYNEWT_VAL(TIMER_1)
+struct nrf52_hal_timer nrf52_hal_timer1;
+#endif
+#if MYNEWT_VAL(TIMER_2)
+struct nrf52_hal_timer nrf52_hal_timer2;
+#endif
+#if MYNEWT_VAL(TIMER_3)
+struct nrf52_hal_timer nrf52_hal_timer3;
+#endif
+#if MYNEWT_VAL(TIMER_4)
+struct nrf52_hal_timer nrf52_hal_timer4;
+#endif
+#if MYNEWT_VAL(TIMER_5)
+struct nrf52_hal_timer nrf52_hal_timer5;
+#endif
+
+static const struct nrf52_hal_timer *nrf52_hal_timers[NRF52_HAL_TIMER_MAX] = {
+#if MYNEWT_VAL(TIMER_0)
+    &nrf52_hal_timer0,
+#else
+    NULL,
+#endif
+#if MYNEWT_VAL(TIMER_1)
+    &nrf52_hal_timer1,
+#else
+    NULL,
+#endif
+#if MYNEWT_VAL(TIMER_2)
+    &nrf52_hal_timer2,
+#else
+    NULL,
+#endif
+#if MYNEWT_VAL(TIMER_3)
+    &nrf52_hal_timer3,
+#else
+    NULL,
+#endif
+#if MYNEWT_VAL(TIMER_4)
+    &nrf52_hal_timer4,
+#else
+    NULL,
+#endif
+#if MYNEWT_VAL(TIMER_5)
+    &nrf52_hal_timer5
+#else
+    NULL
+#endif
+};
+
+/* Resolve timer number into timer structure */
+#define NRF52_HAL_TIMER_RESOLVE(__n, __v)       \
+    if ((__n) >= NRF52_HAL_TIMER_MAX) {         \
+        rc = EINVAL;                            \
+        goto err;                               \
+    }                                           \
+    (__v) = (struct nrf52_hal_timer *) nrf52_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 */
+    nrf_timer_task_trigger(hwtimer, NRF_TIMER_TASK_CAPTURE2);
+    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 nrf52_hal_timer *bsptimer, uint32_t expiry)
+{
+    int32_t delta_t;
+    uint32_t temp;
+    uint32_t cntr;
+    NRF_TIMER_Type *hwtimer;
+    NRF_RTC_Type *rtctimer;
+
+    if (bsptimer->tmr_rtc) {
+        rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
+        nrf_rtc_int_disable(rtctimer, NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT));
+        temp = bsptimer->tmr_cntr;
+        cntr = nrf_rtc_counter_get(rtctimer);
+        if (rtctimer->EVENTS_OVRFLW) {
+            temp += (1UL << 24);
+            cntr = nrf_rtc_counter_get(rtctimer);
+        }
+        temp |= cntr;
+        delta_t = (int32_t)(expiry - temp);
+
+        /*
+         * The nRF52xxx documentation states that COMPARE event is guaranteed
+         * only if value written to CC register is at least 2 greater than the
+         * current counter value. We also need to account for possible extra
+         * tick during calculations so effectively any delta less than 3 needs
+         * to be handled differently. TICK event is used to have interrupt on
+         * each subsequent tick so we won't miss any and in case we detected
+         * mentioned extra tick during calculations, interrupt is triggered
+         * immediately. Delta 0 or less means we should always fire immediately.
+         */
+        if (delta_t < 1) {
+            nrf_rtc_int_disable(rtctimer, RTC_INTENCLR_TICK_Msk);
+            NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
+        } else if (delta_t < 3 && 0) {
+            nrf_rtc_int_enable(rtctimer, RTC_INTENSET_TICK_Msk);
+	    if (nrf_rtc_counter_get(rtctimer) != cntr) {
+                NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
+            }
+        } else {
+            nrf_rtc_int_disable(rtctimer, RTC_INTENCLR_TICK_Msk);
+
+            if (delta_t < (1UL << 24)) {
+                nrf_rtc_cc_set(rtctimer, NRF_RTC_TIMER_CC_INT, expiry & 0x00ffffff);
+            } else {
+                /* CC too far ahead. Just make sure we set compare far ahead */
+                nrf_rtc_cc_set(rtctimer, NRF_RTC_TIMER_CC_INT, cntr + (1UL << 23));
+            }
+            nrf_rtc_int_enable(rtctimer, NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT));
+        }
+    } else {
+        hwtimer = bsptimer->tmr_reg;
+
+        /* Disable ocmp interrupt and set new value */
+        nrf_timer_int_disable(hwtimer, NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT));
+
+        /* Set output compare register to timer expiration */
+        nrf_timer_cc_set(hwtimer, NRF_TIMER_CC_INT, expiry);
+
+        /* Clear interrupt flag */
+        hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT] = 0;
+
+        /* Enable the output compare interrupt */
+        nrf_timer_int_enable(hwtimer, 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) {
+            NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
+        }
+    }
+}
+
+/* Disable output compare used for timer */
+static void
+nrf_timer_disable_ocmp(NRF_TIMER_Type *hwtimer)
+{
+    nrf_timer_int_disable(hwtimer, NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT));
+}
+
+static void
+nrf_rtc_disable_ocmp(NRF_RTC_Type *rtctimer)
+{
+    nrf_rtc_int_disable(rtctimer, NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT));
+    nrf_rtc_int_disable(rtctimer, RTC_INTENCLR_TICK_Msk);
+}
+
+static uint32_t
+hal_timer_read_bsptimer(struct nrf52_hal_timer *bsptimer)
+{
+    uint32_t low32;
+    uint32_t ctx;
+    uint32_t tcntr;
+    NRF_RTC_Type *rtctimer;
+
+    rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
+    __HAL_DISABLE_INTERRUPTS(ctx);
+    tcntr = bsptimer->tmr_cntr;
+    low32 = nrf_rtc_counter_get(rtctimer);
+    if (rtctimer->EVENTS_OVRFLW) {
+        tcntr += (1UL << 24);
+        bsptimer->tmr_cntr = tcntr;
+        low32 = nrf_rtc_counter_get(rtctimer);
+        rtctimer->EVENTS_OVRFLW = 0;
+        NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
+    }
+    tcntr |= low32;
+    __HAL_ENABLE_INTERRUPTS(ctx);
+
+    return tcntr;
+}
+
+#if (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(TIMER_2) || \
+     MYNEWT_VAL(TIMER_3) || MYNEWT_VAL(TIMER_4) || MYNEWT_VAL(TIMER_5))
+/**
+ * hal timer chk queue
+ *
+ *
+ * @param bsptimer
+ */
+static void
+hal_timer_chk_queue(struct nrf52_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_rtc) {
+            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 {
+        if (bsptimer->tmr_rtc) {
+            nrf_rtc_disable_ocmp((NRF_RTC_Type *)bsptimer->tmr_reg);
+        } 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) || \
+     MYNEWT_VAL(TIMER_3) || MYNEWT_VAL(TIMER_4))
+
+static void
+hal_timer_irq_handler(struct nrf52_hal_timer *bsptimer)
+{
+    uint32_t compare;
+    NRF_TIMER_Type *hwtimer;
+
+    os_trace_isr_enter();
+
+    /* 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;
+    }
+
+    /* XXX: make these stats? */
+    /* 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.
+     */
+    if (hwtimer->INTENCLR & NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT)) {
+        hal_timer_chk_queue(bsptimer);
+        /* XXX: Recommended by nordic to make sure interrupts are cleared */
+        compare = hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT];
+    }
+
+    os_trace_isr_exit();
+}
+#endif
+
+#if MYNEWT_VAL(TIMER_5)
+static void
+hal_rtc_timer_irq_handler(struct nrf52_hal_timer *bsptimer)
+{
+    uint32_t overflow;
+    uint32_t compare;
+    uint32_t tick;
+    NRF_RTC_Type *rtctimer;
+
+    os_trace_isr_enter();
+
+    /* Check interrupt source. If set, clear them */
+    rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
+    compare = rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT];
+    if (compare) {
+       rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT] = 0;
+    }
+
+    tick = rtctimer->EVENTS_TICK;
+    if (tick) {
+        rtctimer->EVENTS_TICK = 0;
+    }
+
+    overflow = rtctimer->EVENTS_OVRFLW;
+    if (overflow) {
+        rtctimer->EVENTS_OVRFLW = 0;
+        bsptimer->tmr_cntr += (1UL << 24);
+    }
+
+    /* 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 = rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT];
+
+    os_trace_isr_exit();
+}
+#endif
+
+#if MYNEWT_VAL(TIMER_0)
+void
+nrf52_timer0_irq_handler(void)
+{
+    hal_timer_irq_handler(&nrf52_hal_timer0);
+}
+#endif
+
+#if MYNEWT_VAL(TIMER_1)
+void
+nrf52_timer1_irq_handler(void)
+{
+    hal_timer_irq_handler(&nrf52_hal_timer1);
+}
+#endif
+
+#if MYNEWT_VAL(TIMER_2)
+void
+nrf52_timer2_irq_handler(void)
+{
+    hal_timer_irq_handler(&nrf52_hal_timer2);
+}
+#endif
+
+#if MYNEWT_VAL(TIMER_3)
+void
+nrf52_timer3_irq_handler(void)
+{
+    hal_timer_irq_handler(&nrf52_hal_timer3);
+}
+#endif
+
+#if MYNEWT_VAL(TIMER_4)
+void
+nrf52_timer4_irq_handler(void)
+{
+    hal_timer_irq_handler(&nrf52_hal_timer4);
+}
+#endif
+
+#if MYNEWT_VAL(TIMER_5)
+void
+nrf52_timer5_irq_handler(void)
+{
+    hal_rtc_timer_irq_handler(&nrf52_hal_timer5);
+}
+#endif
+
+/**
+ * hal timer init
+ *
+ * Initialize platform specific timer items
+ *
+ * @param timer_num     Timer number to initialize
+ * @param cfg           Pointer to platform specific configuration
+ *
+ * @return int          0: success; error code otherwise
+ */
+int
+hal_timer_init(int timer_num, void *cfg)
+{
+    int rc;
+    uint8_t irq_num;
+    struct nrf52_hal_timer *bsptimer;
+    void *hwtimer;
+    hal_timer_irq_handler_t irq_isr;
+
+    NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
+
+    /* If timer is enabled do not allow init */
+    if (bsptimer->tmr_enabled) {
+        rc = EINVAL;
+        goto err;
+    }
+
+    switch (timer_num) {
+#if MYNEWT_VAL(TIMER_0)
+    case 0:
+        irq_num = TIMER0_IRQn;
+        hwtimer = NRF_TIMER0;
+        irq_isr = nrf52_timer0_irq_handler;
+        break;
+#endif
+#if MYNEWT_VAL(TIMER_1)
+    case 1:
+        irq_num = TIMER1_IRQn;
+        hwtimer = NRF_TIMER1;
+        irq_isr = nrf52_timer1_irq_handler;
+        break;
+#endif
+#if MYNEWT_VAL(TIMER_2)
+    case 2:
+        irq_num = TIMER2_IRQn;
+        hwtimer = NRF_TIMER2;
+        irq_isr = nrf52_timer2_irq_handler;
+        break;
+#endif
+#if MYNEWT_VAL(TIMER_3)
+    case 3:
+        irq_num = TIMER3_IRQn;
+        hwtimer = NRF_TIMER3;
+        irq_isr = nrf52_timer3_irq_handler;
+        break;
+#endif
+#if MYNEWT_VAL(TIMER_4)
+    case 4:
+        irq_num = TIMER4_IRQn;
+        hwtimer = NRF_TIMER4;
+        irq_isr = nrf52_timer4_irq_handler;
+        break;
+#endif
+#if MYNEWT_VAL(TIMER_5)
+    case 5:
+        irq_num = RTC0_IRQn;
+        hwtimer = NRF_RTC0;
+        irq_isr = nrf52_timer5_irq_handler;
+        bsptimer->tmr_rtc = 1;
+        break;
+#endif
+    default:
+        hwtimer = NULL;
+        break;
+    }
+
+    if (hwtimer == NULL) {
+        rc = EINVAL;
+        goto err;
+    }
+
+    bsptimer->tmr_reg = hwtimer;
+    bsptimer->tmr_irq_num = irq_num;
+
+    /* Disable IRQ, set priority and set vector in table */
+    NVIC_DisableIRQ(irq_num);
+    NVIC_SetPriority(irq_num, (1 << __NVIC_PRIO_BITS) - 1);
+    NVIC_SetVector(irq_num, (uint32_t)irq_isr);
+
+    return 0;
+
+err:
+    return rc;
+}
+
+/**
+ * hal timer config
+ *
+ * Configure a timer to run at the desired frequency. This starts the timer.
+ *
+ * @param timer_num
+ * @param freq_hz
+ *
+ * @return int
+ */
+int
+hal_timer_config(int timer_num, uint32_t freq_hz)
+{
+    int rc;
+    uint8_t prescaler;
+    uint32_t ctx;
+    uint32_t div;
+    uint32_t min_delta;
+    uint32_t max_delta;
+    struct nrf52_hal_timer *bsptimer;
+    NRF_TIMER_Type *hwtimer;
+#if MYNEWT_VAL(TIMER_5)
+    NRF_RTC_Type *rtctimer;
+#endif
+
+    NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
+
+#if MYNEWT_VAL(TIMER_5)
+    if (timer_num == 5) {
+        /* NOTE: we only allow the RTC frequency to be set at 32768 */
+        if (bsptimer->tmr_enabled || (freq_hz != 32768) ||
+            (bsptimer->tmr_reg == NULL)) {
+            rc = EINVAL;
+            goto err;
+        }
+
+        bsptimer->tmr_freq = freq_hz;
+        bsptimer->tmr_enabled = 1;
+
+        __HAL_DISABLE_INTERRUPTS(ctx);
+
+        rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
+
+        /* Stop the timer first */
+        nrf_rtc_task_trigger(rtctimer, NRF_RTC_TASK_STOP);
+        nrf_rtc_task_trigger(rtctimer, NRF_RTC_TASK_CLEAR);
+
+        /* Always no prescaler */
+        rtctimer->PRESCALER = 0;
+
+        /* Clear overflow events and set overflow interrupt */
+        rtctimer->EVENTS_OVRFLW = 0;
+        nrf_rtc_int_enable(rtctimer, RTC_INTENSET_OVRFLW_Msk);
+
+        /* Start the timer */
+        nrf_rtc_task_trigger(rtctimer, NRF_RTC_TASK_START);
+        /* Set isr in vector table and enable interrupt */
+        NVIC_EnableIRQ(bsptimer->tmr_irq_num);
+
+        __HAL_ENABLE_INTERRUPTS(ctx);
+        return 0;
+    }
+#endif
+
+    /* Set timer to desired frequency */
+    div = NRF52_MAX_TIMER_FREQ / freq_hz;
+
+    /*
+     * Largest prescaler is 2^9 and must make sure frequency not too high.
+     * If hwtimer is NULL it means that the timer was not initialized prior
+     * to call.
+     */
+    if (bsptimer->tmr_enabled || (div == 0) || (div > 512) ||
+        (bsptimer->tmr_reg == NULL)) {
+        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 = NRF52_MAX_TIMER_FREQ / (1 << prescaler);
+    bsptimer->tmr_enabled = 1;
+
+    /* disable interrupts */
+    __HAL_DISABLE_INTERRUPTS(ctx);
+
+#if MYNEWT_VAL_CHOICE(MCU_HFCLK_SOURCE, HFXO)
+    /* Make sure HFXO is started */
+    nrf52_clock_hfxo_request();
+#endif
+    hwtimer = bsptimer->tmr_reg;
+
+    /* Stop the timer first */
+    nrf_timer_task_trigger(hwtimer, NRF_TIMER_TASK_STOP);
+    nrf_timer_task_trigger(hwtimer, NRF_TIMER_TASK_CLEAR);
+
+    /* Put the timer in timer mode using 32 bits. */
+    nrf_timer_mode_set(hwtimer, NRF_TIMER_MODE_TIMER);
+    hwtimer->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
+
+    /* Set the pre-scalar */
+    hwtimer->PRESCALER = prescaler;
+
+    /* Start the timer */
+    nrf_timer_task_trigger(hwtimer, NRF_TIMER_TASK_START);
+
+    NVIC_EnableIRQ(bsptimer->tmr_irq_num);
+
+    __HAL_ENABLE_INTERRUPTS(ctx);
+
+    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 nrf52_hal_timer *bsptimer;
+    NRF_TIMER_Type *hwtimer;
+    NRF_RTC_Type *rtctimer;
+
+    rc = 0;
+    NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
+
+    __HAL_DISABLE_INTERRUPTS(ctx);
+    if (bsptimer->tmr_rtc) {
+        rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
+        nrf_rtc_int_disable(rtctimer, NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT));
+	nrf_rtc_task_trigger(rtctimer, NRF_RTC_TASK_STOP);
+    } else {
+        hwtimer = (NRF_TIMER_Type *)bsptimer->tmr_reg;
+        nrf_timer_int_disable(hwtimer, NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT));
+        hwtimer->TASKS_SHUTDOWN = 1;
+    }
+    bsptimer->tmr_enabled = 0;
+    bsptimer->tmr_reg = NULL;
+
+#if MYNEWT_VAL_CHOICE(MCU_HFCLK_SOURCE, HFXO)
+    if (timer_num != 5) {
+        nrf52_clock_hfxo_release();
+    }
+#endif
+    __HAL_ENABLE_INTERRUPTS(ctx);
+
+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 nrf52_hal_timer *bsptimer;
+
+    NRF52_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 nrf52_hal_timer *bsptimer;
+
+    NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
+    if (bsptimer->tmr_rtc) {
+        tcntr = hal_timer_read_bsptimer(bsptimer);
+    } else {
+        tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg);
+    }
+
+    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 nrf52_hal_timer *bsptimer;
+
+    NRF52_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 nrf52_hal_timer *bsptimer;
+
+    /* Set the tick value at which the timer should expire */
+    bsptimer = (struct nrf52_hal_timer *)timer->bsp_timer;
+    if (bsptimer->tmr_rtc) {
+        tick = hal_timer_read_bsptimer(bsptimer) + ticks;
+    } else {
+        tick = nrf_read_timer_cntr(bsptimer->tmr_reg) + ticks;
+    }
+    rc = hal_timer_start_at(timer, tick);
+    return rc;
+}
+
+int
+hal_timer_start_at(struct hal_timer *timer, uint32_t tick)
+{
+    uint32_t ctx;
+    struct hal_timer *entry;
+    struct nrf52_hal_timer *bsptimer;
+
+    if ((timer == NULL) || (timer->link.tqe_prev != NULL) ||
+        (timer->cb_func == NULL)) {
+        return EINVAL;
+    }
+    bsptimer = (struct nrf52_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 nrf52_hal_timer *bsptimer;
+
+    if (timer == NULL) {
+        return EINVAL;
+    }
+
+   bsptimer = (struct nrf52_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 nrf52_hal_timer *)entry->bsp_timer,
+                                   entry->expiry);
+            } else {
+                if (bsptimer->tmr_rtc) {
+                    nrf_rtc_disable_ocmp((NRF_RTC_Type *)bsptimer->tmr_reg);
+                } else {
+                    nrf_timer_disable_ocmp(bsptimer->tmr_reg);
+                }
+            }
+        }
+    }
+
+    __HAL_ENABLE_INTERRUPTS(ctx);
+
+    return 0;
+}
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_uart.c b/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_uart.c
new file mode 100644
index 0000000..41ac9b1
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_uart.c
@@ -0,0 +1,478 @@
+/*
+ * 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 "os/mynewt.h"
+#include "hal/hal_uart.h"
+#include "bsp/bsp.h"
+
+#ifdef MN_LINUX
+#include <pty.h>
+#endif
+#ifdef MN_OSX
+#include <util.h>
+#endif
+#ifdef MN_FreeBSD
+#include <libutil.h>
+#endif
+#include <ctype.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <unistd.h>
+#include <string.h>
+#include <termios.h>
+#include <errno.h>
+
+#include "mcu/mcu_sim.h"
+#include "native_uart_cfg_priv.h"
+#include "syscfg/syscfg.h"
+
+#define UART_CNT                2
+
+#if MYNEWT_VAL(CONSOLE_UART_TX_BUF_SIZE)
+#define UART_MAX_BYTES_PER_POLL	MYNEWT_VAL(CONSOLE_UART_TX_BUF_SIZE) - 2
+#else
+#define UART_MAX_BYTES_PER_POLL	64
+#endif
+#define UART_POLLER_STACK_SZ	OS_STACK_ALIGN(1024)
+
+struct uart {
+    int u_open;
+    int u_fd;
+    int u_tx_run;
+    int u_rx_char;
+    hal_uart_rx_char u_rx_func;
+    hal_uart_tx_char u_tx_func;
+    hal_uart_tx_done u_tx_done;
+    void *u_func_arg;
+};
+
+const char *native_uart_dev_strs[UART_CNT];
+
+/*
+ * XXXX should try to use O_ASYNC/SIGIO for byte arrival notification,
+ * so we wouldn't need an OS for pseudo ttys.
+ */
+char *native_uart_log_file = NULL;
+static int uart_log_fd = -1;
+
+static struct uart uarts[UART_CNT];
+static int uart_poller_running;
+static struct os_task uart_poller_task;
+static os_stack_t uart_poller_stack[UART_POLLER_STACK_SZ];
+
+static void
+uart_open_log(void)
+{
+    if (native_uart_log_file && uart_log_fd < 0) {
+        uart_log_fd = open(native_uart_log_file, O_WRONLY | O_CREAT | O_TRUNC,
+                0666);
+        assert(uart_log_fd >= 0);
+    }
+}
+
+static void
+uart_log_data(struct uart *u, int istx, uint8_t data)
+{
+    static struct {
+        struct uart *uart;
+        int istx;
+        uint32_t time;
+        int chars_in_line;
+    } state = {
+            .uart = NULL,
+            .istx = 0
+    };
+    uint32_t now;
+    char tmpbuf[32];
+    int len;
+
+    if (uart_log_fd < 0) {
+        return;
+    }
+    now = os_time_get();
+    if (state.uart) {
+        if (u != state.uart || now != state.time || istx != state.istx) {
+            /*
+             * End current printout.
+             */
+            if (write(uart_log_fd, "\n", 1) != 1) {
+                assert(0);
+            }
+            state.uart = NULL;
+        } else {
+            if (state.chars_in_line == 8) {
+                if (write(uart_log_fd, "\n\t", 2) != 2) {
+                    assert(0);
+                }
+                state.chars_in_line = 0;
+            }
+            len = snprintf(tmpbuf, sizeof(tmpbuf), "%c (%02x) ",
+                    isalnum(data) ? data : '?', data);
+            if (write(uart_log_fd, tmpbuf, len) != len) {
+                assert(0);
+            }
+            state.chars_in_line++;
+        }
+    }
+    if (u && state.uart == NULL) {
+        len = snprintf(tmpbuf, sizeof(tmpbuf), "%u:uart%d %s\n\t%c (%02x) ",
+                now, u - uarts, istx ? "tx" : "rx", isalnum(data) ? data : '?', data);
+        if (write(uart_log_fd, tmpbuf, len) != len) {
+            assert(0);
+        }
+        state.chars_in_line = 1;
+        state.uart = u;
+        state.istx = istx;
+        state.time = now;
+    }
+}
+
+static int
+uart_transmit_char(struct uart *uart)
+{
+    int sr;
+    int rc;
+    char ch;
+
+    OS_ENTER_CRITICAL(sr);
+    rc = uart->u_tx_func(uart->u_func_arg);
+    if (rc < 0) {
+        /*
+         * No more data to send.
+         */
+        uart->u_tx_run = 0;
+        if (uart->u_tx_done) {
+            uart->u_tx_done(uart->u_func_arg);
+        }
+        OS_EXIT_CRITICAL(sr);
+        return 0;
+    }
+    ch = rc;
+    uart_log_data(uart, 1, ch);
+    OS_EXIT_CRITICAL(sr);
+    rc = write(uart->u_fd, &ch, 1);
+    if (rc <= 0) {
+        /* XXX EOF/error, what now? */
+        return -1;
+    }
+    return 0;
+}
+
+static void
+uart_poller(void *arg)
+{
+    int i;
+    int rc;
+    int bytes;
+    int sr;
+    int didwork;
+    unsigned char ch;
+    struct uart *uart;
+
+    while (1) {
+        for (i = 0; i < UART_CNT; i++) {
+            if (!uarts[i].u_open) {
+                continue;
+            }
+            uart = &uarts[i];
+
+            for (bytes = 0; bytes < UART_MAX_BYTES_PER_POLL; bytes++) {
+                didwork = 0;
+                if (uart->u_tx_run) {
+                    uart_transmit_char(uart);
+                    didwork = 1;
+                }
+                if (uart->u_rx_char < 0) {
+                    rc = read(uart->u_fd, &ch, 1);
+                    if (rc == 0) {
+                        /* XXX EOF, what now? */
+                        assert(0);
+                    } else if (rc > 0) {
+                        uart->u_rx_char = ch;
+                    }
+                }
+                if (uart->u_rx_char >= 0) {
+                    OS_ENTER_CRITICAL(sr);
+                    uart_log_data(uart, 0, uart->u_rx_char);
+                    rc = uart->u_rx_func(uart->u_func_arg, uart->u_rx_char);
+                    /* Delivered */
+                    if (rc >= 0) {
+                        uart->u_rx_char = -1;
+                        didwork = 1;
+                    }
+                    OS_EXIT_CRITICAL(sr);
+                }
+                if (!didwork) {
+                    break;
+                }
+            }
+        }
+        uart_log_data(NULL, 0, 0);
+        os_time_delay(OS_TICKS_PER_SEC / 100);
+    }
+}
+
+static void
+set_nonblock(int fd)
+{
+    int flags;
+
+    flags = fcntl(fd, F_GETFL);
+    if (flags == -1) {
+        const char msg[] = "fcntl(F_GETFL) fail";
+        write(1, msg, sizeof(msg));
+        return;
+    }
+    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+        const char msg[] = "fcntl(F_SETFL) fail";
+        write(1, msg, sizeof(msg));
+        return;
+    }
+}
+
+static int
+uart_pty_set_attr(int fd)
+{
+    struct termios tios;
+
+    if (tcgetattr(fd, &tios)) {
+        const char msg[] = "tcgetattr() failed";
+        write(1, msg, sizeof(msg));
+        return -1;
+    }
+
+    tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
+    tios.c_cflag |= CS8 | CREAD;
+    tios.c_iflag = IGNPAR;
+    tios.c_oflag = 0;
+    tios.c_lflag = 0;
+    if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
+        const char msg[] = "tcsetattr() failed";
+        write(1, msg, sizeof(msg));
+        return -1;
+    }
+    return 0;
+}
+
+static int
+uart_pty(int port)
+{
+    int fd;
+    int loop_slave;
+    char pty_name[32];
+    char msg[64];
+
+    if (openpty(&fd, &loop_slave, pty_name, NULL, NULL) < 0) {
+        const char msg[] = "openpty() failed";
+        write(1, msg, sizeof(msg));
+        return -1;
+    }
+
+    if (uart_pty_set_attr(loop_slave)) {
+        goto err;
+    }
+
+    snprintf(msg, sizeof(msg), "uart%d at %s\n", port, pty_name);
+    write(1, msg, strlen(msg));
+    return fd;
+    err:
+    close(fd);
+    close(loop_slave);
+    return -1;
+}
+
+/**
+ * Opens an external device terminal (/dev/cu.<...>).
+ */
+static int
+uart_open_dev(int port, int32_t baudrate, uint8_t databits,
+              uint8_t stopbits, enum hal_uart_parity parity,
+              enum hal_uart_flow_ctl flow_ctl)
+{
+    const char *filename;
+    int fd;
+    int rc;
+
+    filename = native_uart_dev_strs[port];
+    assert(filename != NULL);
+
+    fd = open(filename, O_RDWR);
+    if (fd < 0) {
+        return -1;
+    }
+
+    rc = uart_dev_set_attr(fd, baudrate, databits,
+            stopbits, parity, flow_ctl);
+    if (rc != 0) {
+        close(fd);
+        return rc;
+    }
+
+    dprintf(1, "uart%d at %s\n", port, filename);
+
+    return fd;
+}
+
+void
+hal_uart_start_tx(int port)
+{
+    int sr;
+
+    if (port >= UART_CNT || uarts[port].u_open == 0) {
+        return;
+    }
+    OS_ENTER_CRITICAL(sr);
+    uarts[port].u_tx_run = 1;
+    if (!os_started()) {
+        /*
+         * XXX this is a hack.
+         */
+        uart_transmit_char(&uarts[port]);
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+
+void
+hal_uart_start_rx(int port)
+{
+    /* nothing to do here */
+}
+
+void
+hal_uart_blocking_tx(int port, uint8_t data)
+{
+    if (port >= UART_CNT || uarts[port].u_open == 0) {
+        return;
+    }
+
+    /* XXX: Count statistics and add error checking here. */
+    (void) write(uarts[port].u_fd, &data, sizeof(data));
+}
+
+int
+hal_uart_init_cbs(int port, hal_uart_tx_char tx_func, hal_uart_tx_done tx_done,
+                  hal_uart_rx_char rx_func, void *arg)
+{
+    struct uart *uart;
+    int rc;
+
+    if (port >= UART_CNT) {
+        return -1;
+    }
+
+    uart = &uarts[port];
+    if (uart->u_open) {
+        return -1;
+    }
+    uart->u_tx_func = tx_func;
+    uart->u_tx_done = tx_done;
+    uart->u_rx_func = rx_func;
+    uart->u_func_arg = arg;
+    uart->u_rx_char = -1;
+
+    if (!uart_poller_running) {
+        uart_poller_running = 1;
+        rc = os_task_init(&uart_poller_task, "uartpoll", uart_poller, NULL,
+                MYNEWT_VAL(MCU_UART_POLLER_PRIO), OS_WAIT_FOREVER, uart_poller_stack,
+                UART_POLLER_STACK_SZ);
+        assert(rc == 0);
+    }
+    return 0;
+}
+
+int
+hal_uart_config(int port, int32_t baudrate, uint8_t databits, uint8_t stopbits,
+                enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl)
+{
+    struct uart *uart;
+
+    if (port >= UART_CNT) {
+        return -1;
+    }
+
+    uart = &uarts[port];
+    if (uart->u_open) {
+        return -1;
+    }
+
+    if (native_uart_dev_strs[port] == NULL) {
+        uart->u_fd = uart_pty(port);
+    } else {
+        uart->u_fd = uart_open_dev(port, baudrate, databits, stopbits,
+                parity, flow_ctl);
+    }
+
+    if (uart->u_fd < 0) {
+        return -1;
+    }
+    set_nonblock(uart->u_fd);
+
+
+    uart_open_log();
+    uart->u_open = 1;
+    return 0;
+}
+
+int
+hal_uart_close(int port)
+{
+    struct uart *uart;
+    int rc;
+
+    if (port >= UART_CNT) {
+        rc = -1;
+        goto err;
+    }
+
+    uart = &uarts[port];
+    if (!uart->u_open) {
+        rc = -1;
+        goto err;
+    }
+
+    close(uart->u_fd);
+
+    uart->u_open = 0;
+    return (0);
+    err:
+    return (rc);
+}
+
+int
+hal_uart_init(int port, void *arg)
+{
+    return (0);
+}
+
+int
+uart_set_dev(int port, const char *dev_str)
+{
+    if (port < 0 || port >= UART_CNT) {
+        return SYS_EINVAL;
+    }
+
+    if (uarts[port].u_open) {
+        return SYS_EBUSY;
+    }
+
+    native_uart_dev_strs[port] = dev_str;
+
+    return 0;
+}
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_watchdog.c b/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_watchdog.c
new file mode 100644
index 0000000..d94c7e3
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/src/hal_watchdog.c
@@ -0,0 +1,36 @@
+/*
+ * 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 "hal/hal_watchdog.h"
+
+int
+hal_watchdog_init(uint32_t expire_msecs)
+{
+    return (0);
+}
+
+void
+hal_watchdog_enable(void)
+{
+}
+
+void
+hal_watchdog_tickle(void)
+{
+}
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/src/native_uart_cfg.c b/babblesim/hw/mcu/nordic/nrf52_bsim/src/native_uart_cfg.c
new file mode 100644
index 0000000..5e38ac7
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/src/native_uart_cfg.c
@@ -0,0 +1,248 @@
+/*
+ * 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 <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <termios.h>
+
+/* B0 defined in bits/termios.h collides with nrfx/mdk/nrf52.h */
+#undef B0
+
+#include "os/mynewt.h"
+#include "native_uart_cfg_priv.h"
+
+/* uint64 is used here to accommodate speed_t, whatever that is. */
+static const uint64_t uart_baud_table[][2] = {
+#ifdef B50
+    { 50, B50 },
+#endif
+#ifdef B75
+    { 75, B75 },
+#endif
+#ifdef B110
+    { 110, B110 },
+#endif
+#ifdef B134
+    { 134, B134 },
+#endif
+#ifdef B150
+    { 150, B150 },
+#endif
+#ifdef B200
+    { 200, B200 },
+#endif
+#ifdef B300
+    { 300, B300 },
+#endif
+#ifdef B600
+    { 600, B600 },
+#endif
+#ifdef B1200
+    { 1200, B1200 },
+#endif
+#ifdef B1800
+    { 1800, B1800 },
+#endif
+#ifdef B2400
+    { 2400, B2400 },
+#endif
+#ifdef B4800
+    { 4800, B4800 },
+#endif
+#ifdef B9600
+    { 9600, B9600 },
+#endif
+#ifdef B19200
+    { 19200, B19200 },
+#endif
+#ifdef B38400
+    { 38400, B38400 },
+#endif
+#ifdef B57600
+    { 57600, B57600 },
+#endif
+#ifdef B115200
+    { 115200, B115200 },
+#endif
+#ifdef B230400
+    { 230400, B230400 },
+#endif
+#ifdef B460800
+    { 460800, B460800 },
+#endif
+#ifdef B500000
+    { 500000, B500000 },
+#endif
+#ifdef B576000
+    { 576000, B576000 },
+#endif
+#ifdef B921600
+    { 921600, B921600 },
+#endif
+#ifdef B1000000
+    { 1000000, B1000000 },
+#endif
+#ifdef B1152000
+    { 1152000, B1152000 },
+#endif
+#ifdef B1500000
+    { 1500000, B1500000 },
+#endif
+#ifdef B2000000
+    { 2000000, B2000000 },
+#endif
+#ifdef B2500000
+    { 2500000, B2500000 },
+#endif
+#ifdef B3000000
+    { 3000000, B3000000 },
+#endif
+#ifdef B3500000
+    { 3500000, B3500000 },
+#endif
+#ifdef B3710000
+    { 3710000, B3710000 },
+#endif
+#ifdef B4000000
+    { 4000000, B4000000 },
+#endif
+};
+#define UART_BAUD_TABLE_SZ (sizeof uart_baud_table / sizeof uart_baud_table[0])
+
+/**
+ * Returns 0 on failure.
+ */
+speed_t
+uart_baud_to_speed(int_least32_t baud)
+{
+    int i;
+
+    for (i = 0; i < UART_BAUD_TABLE_SZ; i++) {
+        if (uart_baud_table[i][0] == baud) {
+            return uart_baud_table[i][1];
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * Configures an external device terminal (/dev/cu.<...>).
+ */
+int
+uart_dev_set_attr(int fd, int32_t baudrate, uint8_t databits,
+                  uint8_t stopbits, enum hal_uart_parity parity,
+                  enum hal_uart_flow_ctl flow_ctl)
+{
+    struct termios tty;
+    speed_t speed;
+    int rc;
+
+    assert(fd >= 0);
+
+    memset(&tty, 0, sizeof(tty));
+    cfmakeraw(&tty);
+
+    speed = uart_baud_to_speed(baudrate);
+    if (speed == 0) {
+        fprintf(stderr, "invalid baud rate: %d\n", (int)baudrate);
+        assert(0);
+    }
+
+    tty.c_cflag |= (speed | CLOCAL | CREAD);
+
+    /* Set flow control. */
+    switch (flow_ctl) {
+    case HAL_UART_FLOW_CTL_NONE:
+        tty.c_cflag &= ~CRTSCTS;
+        break;
+
+    case HAL_UART_FLOW_CTL_RTS_CTS:
+        tty.c_cflag |= CRTSCTS;
+        break;
+
+    default:
+        fprintf(stderr, "invalid flow control setting: %d\n", flow_ctl);
+        return -1;
+    }
+
+    errno = 0;
+    rc = cfsetospeed(&tty, speed);
+    if (rc != 0) {
+        fprintf(stderr, "cfsetospeed failed; %d (%s) baudrate=%d\n",
+                errno, strerror(errno), (int)baudrate);
+        return -1;
+    }
+
+    errno = 0;
+    rc = cfsetispeed(&tty, speed);
+    if (rc != 0) {
+        fprintf(stderr, "cfsetispeed failed; %d (%s) baudrate=%d\n",
+                errno, strerror(errno), (int)baudrate);
+        return -1;
+    }
+
+    switch (databits) {
+    case 7:
+        tty.c_cflag |= CS7;
+
+        switch (parity) {
+        case HAL_UART_PARITY_ODD:
+            tty.c_cflag |= PARENB;
+            tty.c_cflag |= PARODD;
+            tty.c_cflag &= ~CSTOPB;
+            tty.c_cflag &= ~CSIZE;
+            break;
+
+        case HAL_UART_PARITY_EVEN:
+            tty.c_cflag |= PARENB;
+            tty.c_cflag &= ~PARODD;
+            tty.c_cflag &= ~CSTOPB;
+            tty.c_cflag &= ~CSIZE;
+            break;
+
+        default:
+            return SYS_EINVAL;
+        }
+
+    case 8:
+        if (parity != HAL_UART_PARITY_NONE) {
+            return SYS_EINVAL;
+        }
+        tty.c_cflag |= CS8;
+        tty.c_cflag &= ~PARENB;
+        tty.c_cflag &= ~CSTOPB;
+        tty.c_cflag &= ~CSIZE;
+        break;
+
+    default:
+        return SYS_EINVAL;
+    }
+
+    rc = tcsetattr(fd, TCSANOW, &tty);
+    if (rc != 0) {
+        fprintf(stderr, "tcsetattr failed; %d (%s)\n", errno, strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/src/native_uart_cfg_priv.h b/babblesim/hw/mcu/nordic/nrf52_bsim/src/native_uart_cfg_priv.h
new file mode 100644
index 0000000..786a68a
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/src/native_uart_cfg_priv.h
@@ -0,0 +1,31 @@
+/*
+ * 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_NATIVE_UART_CFG_PRIV_
+#define H_NATIVE_UART_CFG_PRIV_
+
+#include <termios.h>
+#include "hal/hal_uart.h"
+
+speed_t uart_baud_to_speed(int_least32_t baud);
+int uart_dev_set_attr(int fd, int32_t baudrate, uint8_t databits,
+                      uint8_t stopbits, enum hal_uart_parity parity,
+                      enum hal_uart_flow_ctl flow_ctl);
+
+#endif
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/src/nrf52_clock.c b/babblesim/hw/mcu/nordic/nrf52_bsim/src/nrf52_clock.c
new file mode 100644
index 0000000..25ccc7f
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/src/nrf52_clock.c
@@ -0,0 +1,103 @@
+/*
+ * 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 <assert.h>
+#include <stdint.h>
+#include <hal/nrf_clock.h>
+#include <time_machine.h>
+#include "mcu/nrf52_hal.h"
+#include "nrfx.h"
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+
+static uint8_t nrf52_clock_hfxo_refcnt;
+
+/**
+ * Request HFXO clock be turned on. Note that each request must have a
+ * corresponding release.
+ *
+ * @return int 0: hfxo was already on. 1: hfxo was turned on.
+ */
+int
+nrf52_clock_hfxo_request(void)
+{
+    int started;
+    uint32_t ctx;
+
+#if MYNEWT_VAL_CHOICE(MCU_HFCLK_SOURCE, HFINT)
+    /* Cannot enable/disable hfxo if it is not present */
+    assert(0);
+#endif
+
+    started = 0;
+    __HAL_DISABLE_INTERRUPTS(ctx);
+    assert(nrf52_clock_hfxo_refcnt < 0xff);
+    if (nrf52_clock_hfxo_refcnt == 0) {
+        /* Check the current STATE and SRC of HFCLK */
+        if ((NRF_CLOCK->HFCLKSTAT &
+             (CLOCK_HFCLKSTAT_SRC_Msk | CLOCK_HFCLKSTAT_STATE_Msk)) !=
+            (CLOCK_HFCLKSTAT_SRC_Xtal << CLOCK_HFCLKSTAT_SRC_Pos |
+             CLOCK_HFCLKSTAT_STATE_Running << CLOCK_HFCLKSTAT_STATE_Pos)) {
+            NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
+            nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTART);
+            while (!NRF_CLOCK->EVENTS_HFCLKSTARTED) {
+#if BABBLESIM
+                tm_tick();
+#endif
+            }
+        }
+        started = 1;
+    }
+    ++nrf52_clock_hfxo_refcnt;
+    __HAL_ENABLE_INTERRUPTS(ctx);
+
+    return started;
+}
+
+/**
+ * Release the HFXO. This means that the caller no longer needs the HFXO to be
+ * turned on. Each call to release should have been preceeded by a corresponding
+ * call to request the HFXO
+ *
+ *
+ * @return int 0: HFXO not stopped by this call (others using it) 1: HFXO
+ *         stopped.
+ */
+int
+nrf52_clock_hfxo_release(void)
+{
+    int stopped;
+    uint32_t ctx;
+
+#if MYNEWT_VAL_CHOICE(MCU_HFCLK_SOURCE, HFINT)
+    /* Cannot enable/disable hfxo if it is not present */
+    assert(0);
+#endif
+
+    stopped = 0;
+    __HAL_DISABLE_INTERRUPTS(ctx);
+    assert(nrf52_clock_hfxo_refcnt != 0);
+    --nrf52_clock_hfxo_refcnt;
+    if (nrf52_clock_hfxo_refcnt == 0) {
+        nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTOP);
+        stopped = 1;
+    }
+    __HAL_ENABLE_INTERRUPTS(ctx);
+
+    return stopped;
+}
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/src/system_nrf52.c b/babblesim/hw/mcu/nordic/nrf52_bsim/src/system_nrf52.c
new file mode 100644
index 0000000..00224cd
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/src/system_nrf52.c
@@ -0,0 +1,37 @@
+/* Copyright (c) 2012 ARM LIMITED
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice, this
+ *     list of conditions and the following disclaimer.
+ *
+ *   * Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *
+ *   * Neither the name of ARM nor the names of its contributors may be used to
+ *     endorse or promote products derived from this software without specific
+ *     prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "mcu/cmsis_nvic.h"
+#include "nrf.h"
+
+
+void SystemInit(void)
+{
+}
diff --git a/babblesim/hw/mcu/nordic/nrf52_bsim/syscfg.yml b/babblesim/hw/mcu/nordic/nrf52_bsim/syscfg.yml
new file mode 100644
index 0000000..b1bc4b8
--- /dev/null
+++ b/babblesim/hw/mcu/nordic/nrf52_bsim/syscfg.yml
@@ -0,0 +1,526 @@
+# 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.
+#
+
+syscfg.defs:
+    MCU_TARGET:
+        description: >
+            Specifies target MCU, shall be set by BSP.
+        value:
+        restrictions:
+            - $notnull
+        choices:
+            - nRF52810
+            - nRF52811
+            - nRF52832
+            - nRF52840
+
+    MCU_FLASH_MIN_WRITE_SIZE:
+        description: >
+            Specifies the required alignment for internal flash writes.
+            Used internally by the newt tool.
+        value: 1
+
+    MCU_DCDC_ENABLED:
+        description: >
+            Specifies whether or not to enable DC/DC regulator. This requires
+            external circuitry so is defined to be zero by default and
+            expected to be overridden by the BSP.
+        value: 0
+
+    MCU_HFCLK_SOURCE:
+        description: >
+            Selected source for high frequency clock (HFCLK).
+            Selecting HFXO will still mostly use the HFINT but will switch to HFXO when requested (BLE, certain timers, etc...)
+            Selecting HFINT should only be used in the case where an external 32MHz crystal oscillator is not present.
+        value: HFXO
+        choices:
+            - HFXO
+            - HFINT
+        restrictions:
+            - '(MCU_HFCLK_SOURCE == "HFXO") || (MCU_LFCLK_SOURCE != "LFSYNTH")'
+
+    MCU_LFCLK_SOURCE:
+        description: >
+            Selected source for low frequency clock (LFCLK).
+        value:
+        choices:
+            - LFRC      # 32.768 kHz RC oscillator
+            - LFXO      # 32.768 kHz crystal oscillator
+            - LFSYNTH   # 32.768 kHz synthesized from HFCLK
+
+    MCU_I2C_RECOVERY_DELAY_USEC:
+        description: >
+            Time to wait for activity on SCL line after triggering start task
+            before restarting TWI controller. This is to recover from state
+            where controller is unresponsive due to glitch on I2C bus.
+            Note: Default value seems to work fine, but may need to be tuned.
+        value: 100
+
+    MCU_BUS_DRIVER_I2C_USE_TWIM:
+        description: >
+            Enables usage of i2c_nrf52_twim bus driver for I2C.
+            If disabled, standard i2c_hal driver is used.
+        value: 0
+
+    MCU_GPIO_USE_PORT_EVENT:
+        description: >
+            When enabled, hal_gpio will use GPIOTE PORT event instead of PIN
+            events for interrupts. This mode may be less accurate (i.e. pulse
+            length needs to be longer in order to be detected) but it reduces
+            power consumption since it does not require HFCLK to be running.
+            Refer to nRF52xxx Product Specification document for more details.
+        value: 0
+
+    MCU_DEBUG_IGNORE_BKPT:
+       description: >
+            When enabled, asm(bkpt) will be ignored. If not set, it will hit
+            the breakpoint wherever it gets called, For example, reset and crash
+       value: 0
+
+
+# MCU peripherals definitions
+    I2C_0:
+        description: 'Enable nRF52xxx I2C (TWI) 0'
+        value: 0
+        restrictions:
+            - '!(SPI_0_MASTER && ((MCU_TARGET == "nrf52832") || (MCU_TARGET == "nrf52840")))'
+            - '!(SPI_0_SLAVE  && ((MCU_TARGET == "nrf52832") || (MCU_TARGET == "nrf52840")))'
+            - '!(SPI_1_MASTER && (MCU_TARGET == "nrf52811"))'
+            - '!(SPI_1_SLAVE  && (MCU_TARGET == "nrf52811"))'
+    I2C_0_PIN_SCL:
+        description: 'SCL pin for I2C_0'
+        value: ''
+    I2C_0_PIN_SDA:
+        description: 'SDA pin for I2C_0'
+        value: ''
+    I2C_0_FREQ_KHZ:
+        description: 'Frequency [kHz] for I2C_0'
+        value: 100
+
+    I2C_1:
+        description: 'Enable nRF52xxx I2C (TWI) 1'
+        value: 0
+        restrictions:
+            - "!SPI_1_MASTER"
+            - "!SPI_1_SLAVE"
+    I2C_1_PIN_SCL:
+        description: 'SCL pin for I2C_1'
+        value: ''
+    I2C_1_PIN_SDA:
+        description: 'SDA pin for I2C_1'
+        value: ''
+    I2C_1_FREQ_KHZ:
+        description: 'Frequency [kHz] for I2C_1'
+        value: 100
+
+    SPI_0_MASTER:
+        description: 'Enable nRF52xxx SPI Master 0'
+        value: 0
+        restrictions:
+            - "!SPI_0_SLAVE"
+            - '!(I2C_0 && ((MCU_TARGET == "nrf52832") || (MCU_TARGET == "nrf52840")))'
+    SPI_0_MASTER_PIN_SCK:
+        description: 'SCK pin for SPI_0_MASTER'
+        value: ''
+    SPI_0_MASTER_PIN_MOSI:
+        description: 'MOSI pin for SPI_0_MASTER'
+        value: ''
+    SPI_0_MASTER_PIN_MISO:
+        description: 'MISO pin for SPI_0_MASTER'
+        value: ''
+
+    SPI_0_SLAVE:
+        description: 'Enable nRF52xxx SPI Slave 0'
+        value: 0
+        restrictions:
+            - "!SPI_0_MASTER"
+            - '!(I2C_0 && ((MCU_TARGET == "nrf52832") || (MCU_TARGET == "nrf52840")))'
+    SPI_0_SLAVE_PIN_SCK:
+        description: 'SCK pin for SPI_0_SLAVE'
+        value: ''
+    SPI_0_SLAVE_PIN_MOSI:
+        description: 'MOSI pin for SPI_0_SLAVE'
+        value: ''
+    SPI_0_SLAVE_PIN_MISO:
+        description: 'MISO pin for SPI_0_SLAVE'
+        value: ''
+    SPI_0_SLAVE_PIN_SS:
+        description: 'SS pin for SPI_0_SLAVE'
+        value: ''
+
+    SPI_1_MASTER:
+        description: 'Enable nRF52xxx SPI Master 1'
+        value: 0
+        restrictions:
+            - "!SPI_1_SLAVE"
+            - '!(I2C_1 && ((MCU_TARGET == "nrf52832") || (MCU_TARGET == "nrf52840")))'
+            - '!(I2C_0 && ((MCU_TARGET == "nrf52811")))'
+    SPI_1_MASTER_PIN_SCK:
+        description: 'SCK pin for SPI_1_MASTER'
+        value: ''
+    SPI_1_MASTER_PIN_MOSI:
+        description: 'MOSI pin for SPI_1_MASTER'
+        value: ''
+    SPI_1_MASTER_PIN_MISO:
+        description: 'MISO pin for SPI_1_MASTER'
+        value: ''
+
+    SPI_1_SLAVE:
+        description: 'Enable nRF52xxx SPI Slave 1'
+        value: 0
+        restrictions:
+            - "!SPI_1_MASTER"
+            - '!(I2C_1 && ((MCU_TARGET == "nrf52832") || (MCU_TARGET == "nrf52840")))'
+            - '!(I2C_0 && ((MCU_TARGET == "nrf52811")))'
+    SPI_1_SLAVE_PIN_SCK:
+        description: 'SCK pin for SPI_1_SLAVE'
+        value: ''
+    SPI_1_SLAVE_PIN_MOSI:
+        description: 'MOSI pin for SPI_1_SLAVE'
+        value: ''
+    SPI_1_SLAVE_PIN_MISO:
+        description: 'MISO pin for SPI_1_SLAVE'
+        value: ''
+    SPI_1_SLAVE_PIN_SS:
+        description: 'SS pin for SPI_1_SLAVE'
+        value: ''
+
+    SPI_2_MASTER:
+        description: 'Enable nRF52xxx SPI Master 2'
+        value: 0
+        restrictions:
+            - "!SPI_2_SLAVE"
+    SPI_2_MASTER_PIN_SCK:
+        description: 'SCK pin for SPI_2_MASTER'
+        value: ''
+    SPI_2_MASTER_PIN_MOSI:
+        description: 'MOSI pin for SPI_2_MASTER'
+        value: ''
+    SPI_2_MASTER_PIN_MISO:
+        description: 'MISO pin for SPI_2_MASTER'
+        value: ''
+
+    SPI_2_SLAVE:
+        description: 'Enable nRF52xxx SPI Slave 2'
+        value: 0
+        restrictions:
+            - "!SPI_2_MASTER"
+    SPI_2_SLAVE_PIN_SCK:
+        description: 'SCK pin for SPI_2_SLAVE'
+        value: ''
+    SPI_2_SLAVE_PIN_MOSI:
+        description: 'MOSI pin for SPI_2_SLAVE'
+        value: ''
+    SPI_2_SLAVE_PIN_MISO:
+        description: 'MISO pin for SPI_2_SLAVE'
+        value: ''
+    SPI_2_SLAVE_PIN_SS:
+        description: 'SS pin for SPI_2_SLAVE'
+        value: ''
+
+    SPI_3_MASTER:
+        description: 'Enable nRF52xxx SPI Master 3'
+        value: 0
+        restrictions:
+            - 'MCU_TARGET == "nRF52840" || !SPI_3_MASTER'
+    SPI_3_MASTER_PIN_SCK:
+        description: 'SCK pin for SPI_3_MASTER'
+        value: ''
+    SPI_3_MASTER_PIN_MOSI:
+        description: 'MOSI pin for SPI_3_MASTER'
+        value: ''
+    SPI_3_MASTER_PIN_MISO:
+        description: 'MISO pin for SPI_3_MASTER'
+        value: ''
+
+    ADC_0:
+        description: 'Enable nRF52xxx ADC 0'
+        value:  0
+
+    ADC_0_REFMV_0:
+        description: 'reference mV in AREF0 if used'
+        value: 0
+
+    PWM_0:
+        description: 'Enable nRF52xxx PWM 0'
+        value: 0
+    PWM_1:
+        description: 'Enable nRF52xxx PWM 1'
+        value: 0
+    PWM_2:
+        description: 'Enable nRF52xxx PWM 2'
+        value: 0
+    PWM_3:
+        description: 'Enable nRF52xxx PWM 3'
+        value: 0
+        restrictions:
+            - 'MCU_TARGET == "nRF52840" || !PWM_3'
+
+    TRNG:
+        description: 'Enable nRF52xxx TRNG'
+        value: 0
+
+    CRYPTO:
+        description: 'Enable nRF52xxx CRYPTO'
+        value: 0
+
+    UART_0:
+        description: 'Enable nRF52xxx UART0'
+        value: 1
+    UART_0_PIN_TX:
+        description: 'TX pin for UART0'
+        value: ''
+    UART_0_PIN_RX:
+        description: 'RX pin for UART0'
+        value: ''
+    UART_0_PIN_RTS:
+        description: 'RTS pin for UART0'
+        value: -1
+    UART_0_PIN_CTS:
+        description: 'CTS pin for UART0'
+        value: -1
+
+    UART_1:
+        description: 'Enable nRF52xxx UART1'
+        value: 0
+        restrictions:
+            - 'MCU_TARGET == "nRF52840" || !UART_1'
+    UART_1_PIN_TX:
+        description: 'TX pin for UART1'
+        value: ''
+    UART_1_PIN_RX:
+        description: 'RX pin for UART1'
+        value: ''
+    UART_1_PIN_RTS:
+        description: 'RTS pin for UART1'
+        value: -1
+    UART_1_PIN_CTS:
+        description: 'CTS pin for UART1'
+        value: -1
+
+    TEMP:
+        description: 'Enable nRF52xxx internal temperature mesurement'
+        value:  0
+
+    TIMER_0:
+        description: 'Enable nRF52xxx Timer 0'
+        value:  1
+    TIMER_1:
+        description: 'Enable nRF52xxx Timer 1'
+        value:  0
+    TIMER_2:
+        description: 'Enable nRF52xxx Timer 2'
+        value:  0
+    TIMER_3:
+        description: 'Enable nRF52xxx Timer 3'
+        value:  0
+    TIMER_4:
+        description: 'Enable nRF52xxx Timer 4'
+        value:  0
+    TIMER_5:
+        description: 'Enable nRF52xxx RTC 0'
+        value:  0
+
+    QSPI_ENABLE:
+        description: 'NRF52 QSPI'
+        value: 0
+
+    QSPI_READOC:
+        description: >
+            QSPI Command to use
+            0 - 0x09 Fast Read
+            1 - 0x3B Fast Read Dual Output
+            2 - 0xBB Fast Read Dual I/O
+            3 - 0x6B Fast Read Quad Output
+            4 - 0xEB Fast Read Quad I/O
+        value: 0
+    QSPI_WRITEOC:
+        description: >
+            QSPI Command to use
+            0 - 0x02 Page program
+            1 - 0xA2 Page program Dual Data
+            2 - 0x32 Page program Quad Data
+            3 - 0x38 Page program Quad I/O
+        value: 0
+    QSPI_ADDRMODE:
+        description: 'Address lentgh 0=24 bits, 1=32 bits'
+        value: 0
+    QSPI_DPMCONFIG:
+        description: 'Deep power mode enable'
+        value: 0
+    QSPI_SCK_DELAY:
+        description: >
+            Minimum amount of time that the CSN pin must stay high
+            before it can go low again. Value is specified in number of 16
+            MHz periods (62.5 ns).
+        value: 0
+    QSPI_SCK_FREQ:
+        description: '32MHz clock divider (0-31). Clock = 32MHz / (1+divider)'
+        value: 0
+    QSPI_SPI_MODE:
+        description: 'SPI 0=Mode0 or 1=Mode3'
+        value: 0
+
+    QSPI_FLASH_SECTOR_SIZE:
+        description: 'QSPI sector size. In most cases it should be 4096.'
+        value: 0
+    QSPI_FLASH_PAGE_SIZE:
+        description: >
+            QSPI page size. Writes can only be performed to one page at a time.
+            In most cases it should be 256.
+        value: 0
+
+    QSPI_FLASH_SECTOR_COUNT:
+        description: 'QSPI sector count'
+        value: -1
+    QSPI_PIN_CS:
+        description: 'CS pin for QSPI'
+        value: -1
+    QSPI_PIN_SCK:
+        description: 'SCK pin for QSPI'
+        value: -1
+    QSPI_PIN_DIO0:
+        description: 'DIO0 pin for QSPI'
+        value: -1
+    QSPI_PIN_DIO1:
+        description: 'DIO1 pin for QSPI'
+        value: -1
+    QSPI_PIN_DIO2:
+        description: 'DIO2 pin for QSPI'
+        value: -1
+    QSPI_PIN_DIO3:
+        description: 'DIO3 pin for QSPI'
+        value: -1
+
+    NFC_PINS_AS_GPIO:
+        description: 'Use NFC pins as GPIOs instead of NFC functionality'
+        value: 1
+
+    GPIO_AS_PIN_RESET:
+        description: 'Enable pin reset'
+        value: 0
+
+# Deprecated settings
+
+    MCU_NRF52832:
+        description: Use MCU_TARGET instead
+        value: 0
+        restrictions:
+            - "!MCU_NRF52840"
+        deprecated: 1
+    MCU_NRF52840:
+        description: Use MCU_TARGET instead
+        value: 0
+        restrictions:
+            - "!MCU_NRF52832"
+        deprecated: 1
+
+    XTAL_32768:
+        description: Use MCU_LFCLK_SOURCE instead
+        value: 0
+        restrictions:
+            - "!XTAL_RC"
+            - "!XTAL_32768_SYNTH"
+        deprecated: 1
+    XTAL_RC:
+        description: Use MCU_LFCLK_SOURCE instead
+        value: 0
+        restrictions:
+            - "!XTAL_32768"
+            - "!XTAL_32768_SYNTH"
+        deprecated: 1
+    XTAL_32768_SYNTH:
+        description: Use MCU_LFCLK_SOURCE instead
+        value: 0
+        restrictions:
+            - "!XTAL_32768"
+            - "!XTAL_RC"
+        deprecated: 1
+
+    MCU_NATIVE_USE_SIGNALS:
+        description: >
+            Whether to use POSIX signals to implement context switches.  Valid
+            values are as follows:
+                1: More correctness; less stability.  The OS tick timer will
+                   cause a high-priority task to preempt a low-priority task.
+                   This causes stability issues because a task can be preempted
+                   while it is in the middle of a system call, potentially
+                   causing deadlock or memory corruption.
+
+                0: Less correctness; more stability.  The OS tick timer only
+                   runs while the idle task is active.  Therefore, a sleeping
+                   high-priority task will not preempt a low-priority task due
+                   to a timing event (e.g., delay or callout expired).
+                   However, this version of sim does not suffer from the
+                   stability issues that affect the "signals" implementation.
+
+            Unit tests should use 1.  Long-running sim processes should use 0.
+
+        value: 1
+    MCU_NATIVE:
+        description: >
+            Set to indicate that we are using native mcu.
+        value: 1
+    MCU_FLASH_STYLE_ST:
+        description: Emulated flash layout is similar to one in STM32.
+        value: 1
+        restrictions:
+            - "!MCU_FLASH_STYLE_NORDIC"
+    MCU_FLASH_STYLE_NORDIC:
+        description: >
+            Emulated flash layout is similar to one in NRF51/2 and SAMD21.
+        value: 0
+        restrictions:
+            - "!MCU_FLASH_STYLE_ST"
+    MCU_UART_POLLER_PRIO:
+        description: 'Priority of native UART poller task.'
+        type: task_priority
+        value: 1
+    MCU_TIMER_POLLER_PRIO:
+        description: 'Priority of native HAL timer task.'
+        type: task_priority
+        value: 0
+
+syscfg.vals:
+    OS_TICKS_PER_SEC: 128
+
+syscfg.vals.MCU_NRF52832:
+    MCU_TARGET: nRF52832
+syscfg.vals.MCU_NRF52840:
+    MCU_TARGET: nRF52840
+
+syscfg.vals.XTAL_32768:
+    MCU_LFCLK_SOURCE: LFXO
+syscfg.vals.XTAL_RC:
+    MCU_LFCLK_SOURCE: LFRC
+syscfg.vals.XTAL_32768_SYNTH:
+    MCU_LFCLK_SOURCE: LFSYNTH
+
+syscfg.restrictions:
+    - "!I2C_0 || (I2C_0_PIN_SCL && I2C_0_PIN_SDA)"
+    - "!I2C_1 || (I2C_1_PIN_SCL && I2C_1_PIN_SDA)"
+    - "!SPI_0_MASTER || (SPI_0_MASTER_PIN_SCK && SPI_0_MASTER_PIN_MOSI && SPI_0_MASTER_PIN_MISO)"
+    - "!SPI_1_MASTER || (SPI_1_MASTER_PIN_SCK && SPI_1_MASTER_PIN_MOSI && SPI_1_MASTER_PIN_MISO)"
+    - "!SPI_2_MASTER || (SPI_2_MASTER_PIN_SCK && SPI_2_MASTER_PIN_MOSI && SPI_2_MASTER_PIN_MISO)"
+    - "!SPI_3_MASTER || (SPI_3_MASTER_PIN_SCK && SPI_3_MASTER_PIN_MOSI && SPI_3_MASTER_PIN_MISO)"
+    - "!SPI_0_SLAVE || (SPI_0_SLAVE_PIN_SCK && SPI_0_SLAVE_PIN_MOSI && SPI_0_SLAVE_PIN_MISO && SPI_0_SLAVE_PIN_SS)"
+    - "!SPI_1_SLAVE || (SPI_1_SLAVE_PIN_SCK && SPI_1_SLAVE_PIN_MOSI && SPI_1_SLAVE_PIN_MISO && SPI_1_SLAVE_PIN_SS)"
+    - "!SPI_2_SLAVE || (SPI_2_SLAVE_PIN_SCK && SPI_2_SLAVE_PIN_MOSI && SPI_2_SLAVE_PIN_MISO && SPI_2_SLAVE_PIN_SS)"
+    - "!UART_0 || (UART_0_PIN_TX && UART_0_PIN_RX)"
+    - "!UART_1 || (UART_1_PIN_TX && UART_1_PIN_RX)"
+    - "(OS_TICKS_PER_SEC == 128 || OS_TICKS_PER_SEC == 256 || OS_TICKS_PER_SEC == 512 || OS_TICKS_PER_SEC == 1024)"
diff --git a/babblesim/libc/LICENSE b/babblesim/libc/LICENSE
new file mode 100644
index 0000000..b791574
--- /dev/null
+++ b/babblesim/libc/LICENSE
@@ -0,0 +1,133 @@
+Baselibc is based on klibc 1.5.23 and tinyprintf modules.
+None of the GPL-licensed parts of klibc are used.
+
+Baselibc is licensed under the BSD license:
+
+Copyright (c) 2012 Petteri Aimonen <jpa at blc.mail.kapsi.fi>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Kustaa Nyholm or SpareTimeLabs nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The original licenses of the modules are included below:
+
+------------------ Tinyprintf license ------------------
+
+Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Kustaa Nyholm or SpareTimeLabs nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+------------------- klibc license -------------------------
+This license applies to all files in directory and its subdirectories,
+unless otherwise noted in individual files.
+
+
+Some files are derived from files derived from the include/ directory
+of the Linux kernel, and are licensed under the terms of the GNU
+General Public License, version 2, as released by the Free Software
+Foundation, Inc.; incorporated herein by reference.
+[These files are not included in the baselibc.]
+
+                                -----
+
+Some files are derived from files copyrighted by the Regents of The
+University of California, and are available under the following
+license:
+
+Note: The advertising clause in the license appearing on BSD Unix
+files was officially rescinded by the Director of the Office of
+Technology Licensing of the University of California on July 22
+1999. He states that clause 3 is "hereby deleted in its entirety."
+
+ * Copyright (c)
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+
+For all remaining files [of klibc], the following license applies:
+
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * Any copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/babblesim/libc/pkg.yml b/babblesim/libc/pkg.yml
new file mode 100644
index 0000000..297bfa9
--- /dev/null
+++ b/babblesim/libc/pkg.yml
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+pkg.name: babblesim/libc
+pkg.type: sdk
+pkg.description: Functions from apache-mynewt-core/libc that not exists in Linux system.
+pkg.author: "Codecoup"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+  - "@apache-mynewt-core/kernel/os"
diff --git a/babblesim/libc/src/strlcat.c b/babblesim/libc/src/strlcat.c
new file mode 100644
index 0000000..6d95087
--- /dev/null
+++ b/babblesim/libc/src/strlcat.c
@@ -0,0 +1,30 @@
+/*
+ * strlcat.c
+ */
+
+#include <string.h>
+
+size_t strlcat(char *dst, const char *src, size_t size)
+{
+	size_t bytes = 0;
+	char *q = dst;
+	const char *p = src;
+	char ch;
+
+	while (bytes < size && *q) {
+		q++;
+		bytes++;
+	}
+	if (bytes == size)
+		return (bytes + strlen(src));
+
+	while ((ch = *p++)) {
+		if (bytes + 1 < size)
+			*q++ = ch;
+
+		bytes++;
+	}
+
+	*q = '\0';
+	return bytes;
+}
diff --git a/babblesim/libc/src/strlcpy.c b/babblesim/libc/src/strlcpy.c
new file mode 100644
index 0000000..3ec8fd2
--- /dev/null
+++ b/babblesim/libc/src/strlcpy.c
@@ -0,0 +1,26 @@
+/*
+ * strlcpy.c
+ */
+
+#include <string.h>
+
+size_t strlcpy(char *dst, const char *src, size_t size)
+{
+	size_t bytes = 0;
+	char *q = dst;
+	const char *p = src;
+	char ch;
+
+	while ((ch = *p++)) {
+		if (bytes + 1 < size)
+			*q++ = ch;
+
+		bytes++;
+	}
+
+	/* If size == 0 there is no space for a final null... */
+	if (size)
+		*q = '\0';
+
+	return bytes;
+}
diff --git a/babblesim/nrfx/pkg.yml b/babblesim/nrfx/pkg.yml
new file mode 100644
index 0000000..54a385e
--- /dev/null
+++ b/babblesim/nrfx/pkg.yml
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+pkg.name: babblesim/nrfx
+pkg.description: nrfx wrapper for BabbleSim
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "https://mynewt.apache.org/"
+pkg.type: sdk
+
+pkg.cflags: -std=gnu99
+pkg.include_dirs:
+    - src/
+    - src/drivers/
+    - src/hal/
+    - src/mdk/
+
+pkg.deps:
+    - "@apache-mynewt-core/hw/hal"
+
+pkg.pre_build_cmds:
+    scripts/link_nrfx.sh: 1
diff --git a/babblesim/nrfx/scripts/link_nrfx.sh b/babblesim/nrfx/scripts/link_nrfx.sh
new file mode 100755
index 0000000..2b59847
--- /dev/null
+++ b/babblesim/nrfx/scripts/link_nrfx.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# 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.
+#
+
+mkdir -p ./src/
+for f in nrfx.h drivers hal mdk; do
+    ln -sfn ${NRFX_BASE}/${f} ./src/${f}
+done
\ No newline at end of file

[mynewt-nimble] 03/04: apps/blehci: Add support for BabbleSim

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 d81f0708339ce2a8a5c7b6dfc8a1fbc0091be6b6
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Sun Feb 13 19:30:49 2022 +0100

    apps/blehci: Add support for BabbleSim
---
 apps/blehci/src/main.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/apps/blehci/src/main.c b/apps/blehci/src/main.c
index 040c157..e97e542 100644
--- a/apps/blehci/src/main.c
+++ b/apps/blehci/src/main.c
@@ -17,11 +17,10 @@
  * under the License.
  */
 
-#include <assert.h>
 #include "os/mynewt.h"
 
-int
-main(void)
+static int
+main_fn(int argc, char **argv)
 {
     /* Initialize OS */
     sysinit();
@@ -31,3 +30,16 @@ main(void)
     }
     return 0;
 }
+
+int
+main(int argc, char **argv)
+{
+#if BABBLESIM
+    extern void bsim_init(int argc, char** argv, void *main_fn);
+    bsim_init(argc, argv, main_fn);
+#else
+    main_fn(argc, argv);
+#endif
+
+    return 0;
+}
\ No newline at end of file