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