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:14 UTC

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

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