babblesim: Add babblesim pkg

Co-authored-by: Jakub Rotkiewicz <jakub.rotkiewicz@codecoup.pl>
Co-authored-by: Andrzej Kaczmarek <andrzej.kaczmarek@codecoup.pl>
This commit is contained in:
Magdalena Kasenberg
2021-11-25 18:05:43 +01:00
committed by Andrzej Kaczmarek
parent bf31ad05b7
commit 9abe36cc3c
58 changed files with 6428 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
hw/babblesim/components
hw/babblesim/src
nrfx/src
+1
View File
@@ -0,0 +1 @@
BabbleSim support for Apache NimBLE
+30
View File
@@ -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
+51
View File
@@ -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 */
+27
View File
@@ -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
+48
View File
@@ -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
+37
View File
@@ -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 <dev@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
+153
View File
@@ -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;
}
+85
View File
@@ -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;
}
+74
View File
@@ -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();
}
}
+79
View File
@@ -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);
}
+255
View File
@@ -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);
}
+44
View File
@@ -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 <dev@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
+69
View File
@@ -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
+60
View File
@@ -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
@@ -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 */
@@ -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 */
@@ -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
+22
View File
@@ -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"
+45
View File
@@ -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
+22
View File
@@ -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"
+40
View File
@@ -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
+37
View File
@@ -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 <dev@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"
@@ -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);
}
@@ -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
@@ -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
@@ -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;
}
@@ -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) */
@@ -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) */
@@ -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);
}
+175
View File
@@ -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)
{
}
+59
View File
@@ -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;
}
+73
View File
@@ -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
@@ -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
@@ -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__ */
@@ -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_ */
@@ -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__ */
@@ -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_ */
@@ -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_ */
@@ -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_ */
@@ -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 <dev@mynewt.apache.org>"
pkg.homepage: "http://mynewt.apache.org/"
pkg.deps:
- "babblesim/nrfx"
pkg.deps.BLE_CONTROLLER:
- "@apache-mynewt-nimble/nimble/drivers/nrf52"
@@ -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);
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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)
{
}
@@ -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;
}
@@ -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
@@ -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;
}
@@ -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)
{
}
@@ -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)"
+133
View File
@@ -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.
+28
View File
@@ -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"
+30
View File
@@ -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;
}
+26
View File
@@ -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;
}
+37
View File
@@ -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 <dev@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
+24
View File
@@ -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