You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by st...@apache.org on 2016/09/28 00:43:36 UTC
[10/51] [abbrv] [partial] incubator-mynewt-core git commit: directory
re-org, part 1
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/adc_nrf51/src/adc_nrf51.c
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/adc_nrf51/src/adc_nrf51.c b/hw/drivers/adc/adc_nrf51/src/adc_nrf51.c
new file mode 100644
index 0000000..cf57de6
--- /dev/null
+++ b/hw/drivers/adc/adc_nrf51/src/adc_nrf51.c
@@ -0,0 +1,400 @@
+/*
+ * 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>
+#include <adc/adc.h>
+#include <assert.h>
+#include <os/os.h>
+#include <bsp/cmsis_nvic.h>
+
+/* Nordic headers */
+#include <nrf.h>
+#include <nrf_adc.h>
+#include <nrf_drv_adc.h>
+#include <app_error.h>
+
+/**
+ * Weak symbol, this is defined in Nordic drivers but not exported.
+ * Needed for NVIC_SetVector().
+ */
+extern void ADC_IRQHandler(void);
+
+#define NRF_ADC_CHANNEL_COUNT (1)
+
+struct nrf51_adc_stats {
+ uint16_t adc_events;
+ uint16_t adc_events_failed;
+};
+static struct nrf51_adc_stats nrf51_adc_stats;
+
+struct adc_dev *global_adc_dev;
+
+nrf_adc_config_t adc_cfg;
+nrf_drv_adc_config_t *global_adc_config;
+
+struct adc_chan_config nrf51_adc_chans[NRF_ADC_CHANNEL_COUNT];
+nrf_drv_adc_channel_t *nrf_adc_chan;
+
+static void
+nrf51_adc_event_handler(const nrf_drv_adc_evt_t *event)
+{
+ nrf_drv_adc_done_evt_t *done_ev;
+ int rc;
+
+ if (global_adc_dev == NULL) {
+ ++nrf51_adc_stats.adc_events_failed;
+ return;
+ }
+
+ ++nrf51_adc_stats.adc_events;
+
+ /* Right now only data reads supported, assert for unknown event
+ * type.
+ */
+ assert(event->type == NRF_DRV_ADC_EVT_DONE);
+
+ done_ev = (nrf_drv_adc_done_evt_t * const) &event->data.done;
+
+ rc = global_adc_dev->ad_event_handler_func(global_adc_dev,
+ global_adc_dev->ad_event_handler_arg,
+ ADC_EVENT_RESULT, done_ev->p_buffer,
+ done_ev->size * sizeof(nrf_adc_value_t));
+ if (rc != 0) {
+ ++nrf51_adc_stats.adc_events_failed;
+ }
+}
+
+/**
+ * Open the NRF51 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait. If 0 specified, returns immediately
+ * if resource unavailable. If OS_WAIT_FOREVER specified, blocks
+ * until resource is available.
+ * @param arg Argument provided by higher layer to open, in this case
+ * it can be a nrf_drv_saadc_config_t, to override the default
+ * configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+nrf51_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+ struct adc_dev *dev;
+ nrf_drv_adc_config_t *cfg;
+ int rc;
+
+ dev = (struct adc_dev *) odev;
+
+ if (os_started()) {
+ rc = os_mutex_pend(&dev->ad_lock, wait);
+ if (rc != OS_OK) {
+ goto err;
+ }
+ }
+
+ /* Initialize the device */
+ cfg = (nrf_drv_adc_config_t *)arg;
+ rc = nrf_drv_adc_init(cfg, nrf51_adc_event_handler);
+ if (rc != 0) {
+ goto err;
+ }
+
+ global_adc_dev = dev;
+ global_adc_config = arg;
+
+ return (0);
+err:
+ return (rc);
+}
+
+
+/**
+ * Close the NRF51 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+nrf51_adc_close(struct os_dev *odev)
+{
+ struct adc_dev *dev;
+
+ dev = (struct adc_dev *) odev;
+
+ nrf_drv_adc_uninit();
+
+ global_adc_dev = NULL;
+ global_adc_config = NULL;
+
+ if (os_started()) {
+ os_mutex_release(&dev->ad_lock);
+ }
+
+ return (0);
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ * a nrf_drv_adc_channel_config_t
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+nrf51_adc_configure_channel(struct adc_dev *dev, uint8_t cnum,
+ void *cfgdata)
+{
+ nrf_drv_adc_channel_t *cc;
+ nrf_drv_adc_channel_config_t *cc_cfg;
+ nrf_adc_config_t adc_cfg;
+ uint16_t refmv;
+ uint8_t res;
+ int rc;
+
+ rc = -1;
+ if (global_adc_config == NULL) {
+ goto err;
+ }
+
+ cc = (nrf_drv_adc_channel_t *)cfgdata;
+ nrf_adc_chan = cc;
+ cc_cfg = &cc->config.config;
+
+ adc_cfg.reference = cc_cfg->reference |
+ (cc_cfg->external_reference << ADC_CONFIG_EXTREFSEL_Pos);
+ adc_cfg.resolution = cc_cfg->resolution;
+ adc_cfg.scaling = cc_cfg->input;
+ nrf_adc_configure(&adc_cfg);
+ nrf_drv_adc_channel_enable(cc);
+
+ /* Set the resolution and reference voltage for this channel to
+ * enable conversion functions.
+ */
+ switch (adc_cfg.resolution) {
+ case NRF_ADC_CONFIG_RES_8BIT:
+ res = 8;
+ break;
+ case NRF_ADC_CONFIG_RES_9BIT:
+ res = 9;
+ break;
+ case NRF_ADC_CONFIG_RES_10BIT:
+ res = 10;
+ break;
+ default:
+ assert(0);
+ }
+
+ switch (adc_cfg.reference) {
+ case NRF_ADC_CONFIG_REF_VBG:
+ refmv = 1200; /* 1.2V for NRF51 */
+ break;
+ case NRF_ADC_CONFIG_REF_EXT_REF0:
+ refmv = bsp_get_refmv(cc_cfg);
+ break;
+ case NRF_ADC_CONFIG_REF_EXT_REF1:
+ refmv = bsp_get_refmv(cc_cfg);
+ break;
+ case NRF_ADC_CONFIG_REF_SUPPLY_ONE_HALF:
+ refmv = bsp_get_refmv(cc_cfg) / 2;
+ break;
+ case NRF_ADC_CONFIG_REF_SUPPLY_ONE_THIRD:
+ refmv = bsp_get_refmv(cc_cfg) / 3;
+ break;
+ default:
+ assert(0);
+ }
+
+ /* Adjust reference voltage for gain. */
+ switch (cc_cfg->input) {
+ case NRF_ADC_CONFIG_SCALING_INPUT_FULL_SCALE:
+ break;
+ case NRF_ADC_CONFIG_SCALING_INPUT_ONE_THIRD:
+ refmv *= 3;
+ break;
+ case NRF_ADC_CONFIG_SCALING_INPUT_TWO_THIRDS:
+ refmv = (refmv * 3) / 2;
+ break;
+ case NRF_ADC_CONFIG_SCALING_SUPPLY_ONE_THIRD:
+ refmv = refmv * 3;
+ break;
+ case NRF_ADC_CONFIG_SCALING_SUPPLY_TWO_THIRDS:
+ refmv = (refmv * 3) / 2;
+ break;
+ default:
+ break;
+ }
+
+ /* Store these values in channel definitions, for conversions to
+ * milivolts.
+ */
+ dev->ad_chans[cnum].c_res = res;
+ dev->ad_chans[cnum].c_refmv = refmv;
+ dev->ad_chans[cnum].c_configured = 1;
+
+ return (0);
+err:
+ return (rc);
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Sets both the primary and secondary buffers for DMA.
+ */
+static int
+nrf51_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2,
+ int buf_len)
+{
+ int rc;
+
+ /* XXX: If this is called in blocking mode, it will result in a wait. */
+
+ /* Convert overall buffer length, into a total number of samples which
+ * Nordic APIs expect.
+ */
+ buf_len /= sizeof(nrf_adc_value_t);
+
+ rc = nrf_drv_adc_buffer_convert((nrf_adc_value_t *) buf1, buf_len);
+ if (rc != 0) {
+ goto err;
+ }
+
+ /* XXX: For now, only support one buffer */
+#if 0
+ if (buf2) {
+ rc = nrf_drv_adc_buffer_convert((nrf_adc_value_t *) buf2,
+ buf_len);
+ if (rc != 0) {
+ goto err;
+ }
+ }
+#endif
+ return (0);
+err:
+ return (rc);
+}
+
+static int
+nrf51_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+ int rc;
+
+ buf_len /= sizeof(nrf_adc_value_t);
+
+ rc = nrf_drv_adc_buffer_convert((nrf_adc_value_t *) buf, buf_len);
+ if (rc != 0) {
+ goto err;
+ }
+
+ return (0);
+err:
+ return (rc);
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+nrf51_adc_sample(struct adc_dev *dev)
+{
+ nrf_drv_adc_sample();
+
+ return (0);
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+nrf51_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+ nrf_adc_value_t adc_value;
+ int rc;
+
+ rc = nrf_drv_adc_sample_convert(nrf_adc_chan, &adc_value);
+ if (rc == 0) {
+ *result = (int) adc_value;
+ }
+ return (rc);
+}
+
+static int
+nrf51_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off,
+ int *result)
+{
+ nrf_adc_value_t val;
+ int data_off;
+
+ data_off = off * sizeof(nrf_adc_value_t);
+ assert(data_off < buf_len);
+
+ val = *(nrf_adc_value_t *) ((uint8_t *) buf + data_off);
+ *result = val;
+
+ return (0);
+}
+
+static int
+nrf51_adc_size_buffer(struct adc_dev *dev, int chans, int samples)
+{
+ return (sizeof(nrf_adc_value_t) * chans * samples);
+}
+
+
+/**
+ * Callback to initialize an adc_dev structure from the os device
+ * initialization callback. This sets up a nrf51_adc_device(), so that
+ * subsequent lookups to this device allow us to manipulate it.
+ */
+int
+nrf51_adc_dev_init(struct os_dev *odev, void *arg)
+{
+ struct adc_dev *dev;
+ struct adc_driver_funcs *af;
+
+ dev = (struct adc_dev *) odev;
+
+ os_mutex_init(&dev->ad_lock);
+
+ dev->ad_chans = (void *) nrf51_adc_chans;
+ dev->ad_chan_count = NRF_ADC_CHANNEL_COUNT;
+
+ OS_DEV_SETHANDLERS(odev, nrf51_adc_open, nrf51_adc_close);
+
+ af = &dev->ad_funcs;
+
+ af->af_configure_channel = nrf51_adc_configure_channel;
+ af->af_sample = nrf51_adc_sample;
+ af->af_read_channel = nrf51_adc_read_channel;
+ af->af_set_buffer = nrf51_adc_set_buffer;
+ af->af_release_buffer = nrf51_adc_release_buffer;
+ af->af_read_buffer = nrf51_adc_read_buffer;
+ af->af_size_buffer = nrf51_adc_size_buffer;
+
+ NVIC_SetVector(ADC_IRQn, (uint32_t) ADC_IRQHandler);
+
+ return (0);
+}
+
+
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/adc_nrf52/include/adc_nrf52/adc_nrf52.h
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/adc_nrf52/include/adc_nrf52/adc_nrf52.h b/hw/drivers/adc/adc_nrf52/include/adc_nrf52/adc_nrf52.h
new file mode 100644
index 0000000..f356f89
--- /dev/null
+++ b/hw/drivers/adc/adc_nrf52/include/adc_nrf52/adc_nrf52.h
@@ -0,0 +1,30 @@
+/*
+ * 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 __ADC_NRF52_H__
+#define __ADC_NRF52_H__
+
+#include <adc/adc.h>
+
+#include <nrf.h>
+#include <nrf_saadc.h>
+
+int nrf52_adc_dev_init(struct os_dev *, void *);
+
+#endif /* __ADC_H__ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/adc_nrf52/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/adc_nrf52/pkg.yml b/hw/drivers/adc/adc_nrf52/pkg.yml
new file mode 100644
index 0000000..cd029e5
--- /dev/null
+++ b/hw/drivers/adc/adc_nrf52/pkg.yml
@@ -0,0 +1,28 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: hw/drivers/adc/adc_nrf52
+pkg.description: ADC driver for the NRF52
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+pkg.apis:
+ - ADC_HW_IMPL
+pkg.deps:
+ - hw/drivers/adc
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/adc_nrf52/src/adc_nrf52.c
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/adc_nrf52/src/adc_nrf52.c b/hw/drivers/adc/adc_nrf52/src/adc_nrf52.c
new file mode 100644
index 0000000..d167175
--- /dev/null
+++ b/hw/drivers/adc/adc_nrf52/src/adc_nrf52.c
@@ -0,0 +1,398 @@
+/*
+ * 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>
+#include <adc/adc.h>
+#include <assert.h>
+#include <os/os.h>
+#include <bsp/cmsis_nvic.h>
+
+/* Nordic headers */
+#include <nrf.h>
+#include <nrf_saadc.h>
+#include <nrf_drv_saadc.h>
+#include <app_error.h>
+
+/**
+ * Weak symbol, this is defined in Nordic drivers but not exported.
+ * Needed for NVIC_SetVector().
+ */
+extern void SAADC_IRQHandler(void);
+
+struct nrf52_saadc_stats {
+ uint16_t saadc_events;
+ uint16_t saadc_events_failed;
+};
+static struct nrf52_saadc_stats nrf52_saadc_stats;
+
+struct adc_dev *global_adc_dev;
+nrf_drv_saadc_config_t *global_adc_config;
+
+uint8_t nrf52_adc_chans[NRF_SAADC_CHANNEL_COUNT * sizeof(struct adc_chan_config)];
+
+static void
+nrf52_saadc_event_handler(const nrf_drv_saadc_evt_t *event)
+{
+ nrf_drv_saadc_done_evt_t *done_ev;
+ int rc;
+
+ if (global_adc_dev == NULL) {
+ ++nrf52_saadc_stats.saadc_events_failed;
+ return;
+ }
+
+ ++nrf52_saadc_stats.saadc_events;
+
+ /* Right now only data reads supported, assert for unknown event
+ * type.
+ */
+ assert(event->type == NRF_DRV_SAADC_EVT_DONE);
+
+ done_ev = (nrf_drv_saadc_done_evt_t * const) &event->data.done;
+
+ rc = global_adc_dev->ad_event_handler_func(global_adc_dev,
+ global_adc_dev->ad_event_handler_arg,
+ ADC_EVENT_RESULT, done_ev->p_buffer,
+ done_ev->size * sizeof(nrf_saadc_value_t));
+ if (rc != 0) {
+ ++nrf52_saadc_stats.saadc_events_failed;
+ }
+}
+
+
+/**
+ * Open the NRF52 ADC device
+ *
+ * This function locks the device for access from other tasks.
+ *
+ * @param odev The OS device to open
+ * @param wait The time in MS to wait. If 0 specified, returns immediately
+ * if resource unavailable. If OS_WAIT_FOREVER specified, blocks
+ * until resource is available.
+ * @param arg Argument provided by higher layer to open, in this case
+ * it can be a nrf_drv_saadc_config_t, to override the default
+ * configuration.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+nrf52_adc_open(struct os_dev *odev, uint32_t wait, void *arg)
+{
+ struct adc_dev *dev;
+ int rc;
+
+ dev = (struct adc_dev *) odev;
+
+ if (os_started()) {
+ rc = os_mutex_pend(&dev->ad_lock, wait);
+ if (rc != OS_OK) {
+ goto err;
+ }
+ }
+
+ if (odev->od_flags & OS_DEV_F_STATUS_OPEN) {
+ os_mutex_release(&dev->ad_lock);
+ rc = OS_EBUSY;
+ goto err;
+ }
+
+ /* Initialize the device */
+ rc = nrf_drv_saadc_init((nrf_drv_saadc_config_t *) arg,
+ nrf52_saadc_event_handler);
+ if (rc != 0) {
+ goto err;
+ }
+
+ global_adc_dev = dev;
+ global_adc_config = arg;
+
+ return (0);
+err:
+ return (rc);
+}
+
+
+/**
+ * Close the NRF52 ADC device.
+ *
+ * This function unlocks the device.
+ *
+ * @param odev The device to close.
+ */
+static int
+nrf52_adc_close(struct os_dev *odev)
+{
+ struct adc_dev *dev;
+
+ dev = (struct adc_dev *) odev;
+
+ nrf_drv_saadc_uninit();
+
+ global_adc_dev = NULL;
+ global_adc_config = NULL;
+
+ if (os_started()) {
+ os_mutex_release(&dev->ad_lock);
+ }
+
+ return (0);
+}
+
+/**
+ * Configure an ADC channel on the Nordic ADC.
+ *
+ * @param dev The ADC device to configure
+ * @param cnum The channel on the ADC device to configure
+ * @param cfgdata An opaque pointer to channel config, expected to be
+ * a nrf_saadc_channel_config_t
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+nrf52_adc_configure_channel(struct adc_dev *dev, uint8_t cnum,
+ void *cfgdata)
+{
+ nrf_saadc_channel_config_t *cc;
+ uint16_t refmv;
+ uint8_t res;
+ int rc;
+
+ cc = (nrf_saadc_channel_config_t *) cfgdata;
+
+ rc = nrf_drv_saadc_channel_init(cnum, cc);
+ if (rc != 0) {
+ goto err;
+ }
+
+ if (global_adc_config) {
+ /* Set the resolution and reference voltage for this channel to
+ * enable conversion functions.
+ */
+ switch (global_adc_config->resolution) {
+ case NRF_SAADC_RESOLUTION_8BIT:
+ res = 8;
+ break;
+ case NRF_SAADC_RESOLUTION_10BIT:
+ res = 10;
+ break;
+ case NRF_SAADC_RESOLUTION_12BIT:
+ res = 12;
+ break;
+ case NRF_SAADC_RESOLUTION_14BIT:
+ res = 14;
+ break;
+ default:
+ assert(0);
+ }
+ } else {
+ /* Default to 10-bit resolution. */
+ res = 10;
+ }
+
+ switch (cc->reference) {
+ case NRF_SAADC_REFERENCE_INTERNAL:
+ refmv = 600; /* 0.6V for NRF52 */
+ break;
+ case NRF_SAADC_REFERENCE_VDD4:
+ refmv = bsp_get_refmv(NULL) / 4;
+ break;
+ default:
+ assert(0);
+ }
+
+ /* Adjust reference voltage for gain. */
+ switch (cc->gain) {
+ case NRF_SAADC_GAIN1_6:
+ refmv *= 6;
+ break;
+ case NRF_SAADC_GAIN1_5:
+ refmv *= 5;
+ break;
+ case NRF_SAADC_GAIN1_4:
+ refmv *= 4;
+ break;
+ case NRF_SAADC_GAIN1_3:
+ refmv *= 3;
+ break;
+ case NRF_SAADC_GAIN1_2:
+ refmv *= 2;
+ break;
+ case NRF_SAADC_GAIN2:
+ refmv /= 2;
+ break;
+ case NRF_SAADC_GAIN4:
+ refmv /= 4;
+ break;
+ default:
+ break;
+ }
+
+ /* Store these values in channel definitions, for conversions to
+ * milivolts.
+ */
+ dev->ad_chans[cnum].c_res = res;
+ dev->ad_chans[cnum].c_refmv = refmv;
+ dev->ad_chans[cnum].c_configured = 1;
+
+ return (0);
+err:
+ return (rc);
+}
+
+/**
+ * Set buffer to read data into. Implementation of setbuffer handler.
+ * Sets both the primary and secondary buffers for DMA.
+ */
+static int
+nrf52_adc_set_buffer(struct adc_dev *dev, void *buf1, void *buf2,
+ int buf_len)
+{
+ int rc;
+
+ /* Convert overall buffer length, into a total number of samples which
+ * Nordic APIs expect.
+ */
+ buf_len /= sizeof(nrf_saadc_value_t);
+
+ rc = nrf_drv_saadc_buffer_convert((nrf_saadc_value_t *) buf1, buf_len);
+ if (rc != 0) {
+ goto err;
+ }
+
+ if (buf2) {
+ rc = nrf_drv_saadc_buffer_convert((nrf_saadc_value_t *) buf2,
+ buf_len);
+ if (rc != 0) {
+ goto err;
+ }
+ }
+ return (0);
+err:
+ return (rc);
+}
+
+static int
+nrf52_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len)
+{
+ int rc;
+
+ buf_len /= sizeof(nrf_saadc_value_t);
+
+ rc = nrf_drv_saadc_buffer_convert((nrf_saadc_value_t *) buf, buf_len);
+ if (rc != 0) {
+ goto err;
+ }
+
+ return (0);
+err:
+ return (rc);
+}
+
+/**
+ * Trigger an ADC sample.
+ */
+static int
+nrf52_adc_sample(struct adc_dev *dev)
+{
+ nrf_drv_saadc_sample();
+
+ return (0);
+}
+
+/**
+ * Blocking read of an ADC channel, returns result as an integer.
+ */
+static int
+nrf52_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+ nrf_saadc_value_t adc_value;
+ int rc;
+
+ rc = nrf_drv_saadc_sample_convert(cnum, &adc_value);
+ if (rc != 0) {
+ goto err;
+ }
+
+ *result = (int) adc_value;
+
+ return (0);
+err:
+ return (rc);
+}
+
+static int
+nrf52_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off,
+ int *result)
+{
+ nrf_saadc_value_t val;
+ int data_off;
+
+ data_off = off * sizeof(nrf_saadc_value_t);
+ assert(data_off < buf_len);
+
+ val = *(nrf_saadc_value_t *) ((uint8_t *) buf + data_off);
+ *result = val;
+
+ return (0);
+}
+
+static int
+nrf52_adc_size_buffer(struct adc_dev *dev, int chans, int samples)
+{
+ return (sizeof(nrf_saadc_value_t) * chans * samples);
+}
+
+
+/**
+ * Callback to initialize an adc_dev structure from the os device
+ * initialization callback. This sets up a nrf52_adc_device(), so
+ * that subsequent lookups to this device allow us to manipulate it.
+ */
+int
+nrf52_adc_dev_init(struct os_dev *odev, void *arg)
+{
+ struct adc_dev *dev;
+ struct adc_driver_funcs *af;
+
+ dev = (struct adc_dev *) odev;
+
+ os_mutex_init(&dev->ad_lock);
+
+ dev->ad_chans = (void *) nrf52_adc_chans;
+ dev->ad_chan_count = NRF_SAADC_CHANNEL_COUNT;
+
+ OS_DEV_SETHANDLERS(odev, nrf52_adc_open, nrf52_adc_close);
+
+ af = &dev->ad_funcs;
+
+ af->af_configure_channel = nrf52_adc_configure_channel;
+ af->af_sample = nrf52_adc_sample;
+ af->af_read_channel = nrf52_adc_read_channel;
+ af->af_set_buffer = nrf52_adc_set_buffer;
+ af->af_release_buffer = nrf52_adc_release_buffer;
+ af->af_read_buffer = nrf52_adc_read_buffer;
+ af->af_size_buffer = nrf52_adc_size_buffer;
+
+ NVIC_SetVector(SAADC_IRQn, (uint32_t) SAADC_IRQHandler);
+
+ return (0);
+}
+
+
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/include/adc/adc.h
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/include/adc/adc.h b/hw/drivers/adc/include/adc/adc.h
new file mode 100644
index 0000000..2ffb6cd
--- /dev/null
+++ b/hw/drivers/adc/include/adc/adc.h
@@ -0,0 +1,277 @@
+/*
+ * 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 __ADC_H__
+#define __ADC_H__
+
+#include <os/os_dev.h>
+
+struct adc_dev;
+
+/**
+ * Types of ADC events passed to the ADC driver.
+ */
+typedef enum {
+ /* This event represents the result of an ADC run. */
+ ADC_EVENT_RESULT = 0
+} adc_event_type_t;
+
+/**
+ * Event handler for ADC events that are processed in asynchronous mode.
+ *
+ * @param The ADC device being processed
+ * @param The argument data passed to adc_set_result_handler()
+ * @param The event type
+ * @param The buffer containing event data
+ * @param The size in bytes of that buffer.
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+typedef int (*adc_event_handler_func_t)(struct adc_dev *, void *,
+ adc_event_type_t, void *, int);
+
+/**
+ * Configure an ADC channel for this ADC device. This is implemented
+ * by the HW specific drivers.
+ *
+ * @param The ADC device to configure
+ * @param The channel number to configure
+ * @param An opaque blob containing HW specific configuration.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+typedef int (*adc_configure_channel_func_t)(struct adc_dev *dev, uint8_t,
+ void *);
+
+/**
+ * Trigger a sample on the ADC device asynchronously. This is implemented
+ * by the HW specific drivers.
+ *
+ * @param The ADC device to sample
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+typedef int (*adc_sample_func_t)(struct adc_dev *);
+
+/**
+ * Blocking read of an ADC channel. This is implemented by the HW specific
+ * drivers.
+ *
+ * @param The ADC device to perform the blocking read on
+ * @param The channel to read
+ * @param The result to put the ADC reading into
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+typedef int (*adc_read_channel_func_t)(struct adc_dev *, uint8_t, int *);
+
+/**
+ * Set the buffer(s) to read ADC results into for non-blocking reads. This
+ * is implemented by the HW specific drivers.
+ *
+ * @param The ADC device to read results into
+ * @param The primary buffer to read results into
+ * @param The secondary buffer to read results into (for cases where
+ * DMA'ing occurs, and secondary buffer can be used while primary
+ * is being processed.)
+ * @param The length of both buffers in number of bytes
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+typedef int (*adc_buf_set_func_t)(struct adc_dev *, void *, void *, int);
+
+/**
+ * Release a buffer for an ADC device, allowing the driver to re-use it for
+ * DMA'ing data.
+ *
+ * @param The ADC device to release the buffer to
+ * @param A pointer to the buffer to release
+ * @param The length of the buffer being released.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+typedef int (*adc_buf_release_func_t)(struct adc_dev *, void *, int);
+
+/**
+ * Read the next entry from an ADC buffer as a integer
+ *
+ * @param The ADC device to read the entry from
+ * @param The buffer to read the entry from
+ * @param The total length of the buffer
+ * @param The entry number to read from the buffer
+ * @param The result to put the entry into
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+typedef int (*adc_buf_read_func_t)(struct adc_dev *, void *, int, int, int *);
+
+/**
+ * Get the size of a buffer
+ *
+ * @param The ADC device to get the buffer size from
+ * @param The number of channels in the buffer
+ * @param The number of samples in the buffer
+ *
+ * @return The size of the buffer
+ */
+typedef int (*adc_buf_size_func_t)(struct adc_dev *, int, int);
+
+struct adc_driver_funcs {
+ adc_configure_channel_func_t af_configure_channel;
+ adc_sample_func_t af_sample;
+ adc_read_channel_func_t af_read_channel;
+ adc_buf_set_func_t af_set_buffer;
+ adc_buf_release_func_t af_release_buffer;
+ adc_buf_read_func_t af_read_buffer;
+ adc_buf_size_func_t af_size_buffer;
+};
+
+struct adc_chan_config {
+ uint16_t c_refmv;
+ uint8_t c_res;
+ uint8_t c_configured;
+ uint8_t c_cnum;
+};
+
+struct adc_dev {
+ struct os_dev ad_dev;
+ struct os_mutex ad_lock;
+ struct adc_driver_funcs ad_funcs;
+ struct adc_chan_config *ad_chans;
+ int ad_chan_count;
+ adc_event_handler_func_t ad_event_handler_func;
+ void *ad_event_handler_arg;
+};
+
+int adc_chan_config(struct adc_dev *, uint8_t, void *);
+int adc_chan_read(struct adc_dev *, uint8_t, int *);
+int adc_event_handler_set(struct adc_dev *, adc_event_handler_func_t,
+ void *);
+
+/**
+ * Sample the device specified by dev. This is used in non-blocking mode
+ * to generate samples into the event buffer.
+ *
+ * @param dev The device to sample
+ *
+ * @return 0 on success, non-zero on failure
+ */
+static inline int
+adc_sample(struct adc_dev *dev)
+{
+ return (dev->ad_funcs.af_sample(dev));
+}
+
+/**
+ * Set a result buffer to store data into. Optionally, provide a
+ * second buffer to continue writing data into as the first buffer
+ * fills up. Both buffers must be the same size.
+ *
+ * @param dev The ADC device to set the buffer for
+ * @param buf1 The first buffer to spool data into
+ * @param buf2 The second buffer to spool data into, while the first
+ * buffer is being processed. If NULL is provided, it's
+ * unused.
+ * @param buf_len The length of both buffers, in bytes.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static inline int
+adc_buf_set(struct adc_dev *dev, void *buf1, void *buf2,
+ int buf_len)
+{
+ return (dev->ad_funcs.af_set_buffer(dev, buf1, buf2, buf_len));
+}
+
+/**
+ * Release a result buffer on the ADC device, and allow for it to be
+ * re-used for DMA'ing results.
+ *
+ * @param dev The device to release the buffer for
+ * @param buf The buffer to release
+ * @param buf_len The length of the buffer being released.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+static inline int
+adc_buf_release(struct adc_dev *dev, void *buf, int buf_len)
+{
+ return (dev->ad_funcs.af_release_buffer(dev, buf, buf_len));
+}
+
+/**
+ * Read an entry from an ADC buffer
+ *
+ * @param dev The device that the entry is being read from
+ * @param buf The buffer that we're reading the entry from
+ * @param buf_len The length of the buffer we're reading the entry from
+ * @param off The entry number to read from the buffer
+ * @param result A pointer to the result to store the data in
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+static inline int
+adc_buf_read(struct adc_dev *dev, void *buf, int buf_len, int entry,
+ int *result)
+{
+ return (dev->ad_funcs.af_read_buffer(dev, buf, buf_len, entry, result));
+}
+
+/**
+ * Return the size of an ADC buffer
+ *
+ * @param dev The ADC device to return the buffer size from
+ * @param channels The number of channels for these samples
+ * @param samples The number of SAMPLES on this ADC device
+ *
+ * @return The size of the resulting buffer
+ */
+static inline int
+adc_buf_size(struct adc_dev *dev, int chans, int samples)
+{
+ return (dev->ad_funcs.af_size_buffer(dev, chans, samples));
+}
+
+/**
+ * Take an ADC result and convert it to millivolts.
+ *
+ * @param dev The ADC dev to convert the result on
+ * @param cnum The channel number to convert the result from
+ * @param val The ADC value to convert to millivolts
+ *
+ * @return The convert value in millivolts
+ */
+static inline int
+adc_result_mv(struct adc_dev *dev, uint8_t cnum, int val)
+{
+ int res;
+ int refmv;
+ int ret;
+
+ refmv = (int) dev->ad_chans[cnum].c_refmv;
+ res = (int) dev->ad_chans[cnum].c_res;
+
+ ret = val * refmv;
+ ret += (1 << (res - 2));
+ ret = ret >> res;
+
+ return (ret);
+}
+
+#endif /* __ADC_H__ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/pkg.yml b/hw/drivers/adc/pkg.yml
new file mode 100644
index 0000000..9b69134
--- /dev/null
+++ b/hw/drivers/adc/pkg.yml
@@ -0,0 +1,26 @@
+#
+# 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: hw/drivers/adc
+pkg.description: ADC driver interfaces
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+pkg.req_apis:
+ - ADC_HW_IMPL
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/adc/src/adc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/adc/src/adc.c b/hw/drivers/adc/src/adc.c
new file mode 100644
index 0000000..5eb3440
--- /dev/null
+++ b/hw/drivers/adc/src/adc.c
@@ -0,0 +1,89 @@
+/*
+ * 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 <adc/adc.h>
+#include <errno.h>
+#include <assert.h>
+
+/**
+ * Configure a channel on the ADC device.
+ *
+ * @param dev The device to configure
+ * @param cnum The channel number to configure
+ * @param data Driver specific configuration data for this channel.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+int
+adc_chan_config(struct adc_dev *dev, uint8_t cnum, void *data)
+{
+ assert(dev->ad_funcs.af_configure_channel != NULL);
+
+ if (cnum > dev->ad_chan_count) {
+ return (EINVAL);
+ }
+
+ return (dev->ad_funcs.af_configure_channel(dev, cnum, data));
+}
+
+/**
+ * Blocking read of an ADC channel.
+ *
+ * @param dev The ADC device to read
+ * @param cnum The channel number to read from that device
+ * @param result Where to put the result of the read
+ *
+ * @return 0 on success, non-zero on error
+ */
+int
+adc_chan_read(struct adc_dev *dev, uint8_t cnum, int *result)
+{
+ assert(dev->ad_funcs.af_read_channel != NULL);
+
+ if (cnum > dev->ad_chan_count) {
+ return (EINVAL);
+ }
+
+ if (!dev->ad_chans[cnum].c_configured) {
+ return (EINVAL);
+ }
+
+ return (dev->ad_funcs.af_read_channel(dev, cnum, result));
+}
+
+/**
+ * Set an event handler. This handler is called for all ADC events.
+ *
+ * @param dev The ADC device to set the event handler for
+ * @param func The event handler function to call
+ * @param arg The argument to pass the event handler function
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+adc_event_handler_set(struct adc_dev *dev, adc_event_handler_func_t func,
+ void *arg)
+{
+ dev->ad_event_handler_func = func;
+ dev->ad_event_handler_arg = arg;
+
+ return (0);
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/native/include/ble/xcvr.h
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/native/include/ble/xcvr.h b/hw/drivers/nimble/native/include/ble/xcvr.h
new file mode 100644
index 0000000..54b580c
--- /dev/null
+++ b/hw/drivers/nimble/native/include/ble/xcvr.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 H_BLE_XCVR_
+#define H_BLE_XCVR_
+
+/* Transceiver specific defintions */
+#define XCVR_RX_START_DELAY_USECS (140)
+#define XCVR_TX_START_DELAY_USECS (140)
+#define XCVR_PROC_DELAY_USECS (100)
+#define XCVR_TX_SCHED_DELAY_USECS \
+ (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+#define XCVR_RX_SCHED_DELAY_USECS \
+ (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+
+/*
+ * Define HW whitelist size. This is the total possible whitelist size;
+ * not necessarily the size that will be used (may be smaller)
+ */
+#define BLE_HW_WHITE_LIST_SIZE (0)
+
+#endif /* H_BLE_XCVR_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/native/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/native/pkg.yml b/hw/drivers/nimble/native/pkg.yml
new file mode 100644
index 0000000..bf47e49
--- /dev/null
+++ b/hw/drivers/nimble/native/pkg.yml
@@ -0,0 +1,30 @@
+#
+# 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: hw/drivers/nimble/native
+pkg.description: BLE driver for simulations.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - ble
+ - bluetooth
+
+pkg.apis: ble_driver
+pkg.deps:
+ - net/nimble/controller
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/native/src/ble_hw.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/native/src/ble_hw.c b/hw/drivers/nimble/native/src/ble_hw.c
new file mode 100644
index 0000000..214ad51
--- /dev/null
+++ b/hw/drivers/nimble/native/src/ble_hw.c
@@ -0,0 +1,225 @@
+/**
+ * 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 <assert.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "controller/ble_hw.h"
+
+/* Total number of white list elements supported by nrf52 */
+#define BLE_HW_WHITE_LIST_SIZE (0)
+
+/* We use this to keep track of which entries are set to valid addresses */
+static uint8_t g_ble_hw_whitelist_mask;
+
+/**
+ * Clear the whitelist
+ *
+ * @return int
+ */
+void
+ble_hw_whitelist_clear(void)
+{
+ g_ble_hw_whitelist_mask = 0;
+}
+
+/**
+ * Add a device to the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
+{
+ return BLE_ERR_MEM_CAPACITY;
+}
+
+/**
+ * Remove a device from the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ */
+void
+ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
+{
+ return;
+}
+
+/**
+ * Returns the size of the whitelist in HW
+ *
+ * @return int Number of devices allowed in whitelist
+ */
+uint8_t
+ble_hw_whitelist_size(void)
+{
+ return BLE_HW_WHITE_LIST_SIZE;
+}
+
+/**
+ * Enable the whitelisted devices
+ */
+void
+ble_hw_whitelist_enable(void)
+{
+ return;
+}
+
+/**
+ * Disables the whitelisted devices
+ */
+void
+ble_hw_whitelist_disable(void)
+{
+ return;
+}
+
+/**
+ * Boolean function which returns true ('1') if there is a match on the
+ * whitelist.
+ *
+ * @return int
+ */
+int
+ble_hw_whitelist_match(void)
+{
+ return 0;
+}
+
+/* Encrypt data */
+int
+ble_hw_encrypt_block(struct ble_encryption_block *ecb)
+{
+ return -1;
+}
+
+/**
+ * Initialize the random number generator
+ *
+ * @param cb
+ * @param bias
+ *
+ * @return int
+ */
+int
+ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
+{
+ return -1;
+}
+
+/**
+ * Start the random number generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_start(void)
+{
+ return -1;
+}
+
+/**
+ * Stop the random generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_stop(void)
+{
+ return -1;
+}
+
+/**
+ * Read the random number generator.
+ *
+ * @return uint8_t
+ */
+uint8_t
+ble_hw_rng_read(void)
+{
+ return 0;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+/**
+ * Clear the resolving list
+ *
+ * @return int
+ */
+void
+ble_hw_resolv_list_clear(void)
+{
+}
+
+/**
+ * Add a device to the hw resolving list
+ *
+ * @param irk Pointer to IRK to add
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_resolv_list_add(uint8_t *irk)
+{
+ return BLE_ERR_MEM_CAPACITY;
+}
+
+/**
+ * Remove a device from the hw resolving list
+ *
+ * @param index Index of IRK to remove
+ */
+void
+ble_hw_resolv_list_rmv(int index)
+{
+}
+
+/**
+ * Returns the size of the resolving list. NOTE: this returns the maximum
+ * allowable entries in the HW. Configuration options may limit this.
+ *
+ * @return int Number of devices allowed in resolving list
+ */
+uint8_t
+ble_hw_resolv_list_size(void)
+{
+ return 0;
+}
+
+/**
+ * Called to determine if the address received was resolved.
+ *
+ * @return int Negative values indicate unresolved address; positive values
+ * indicate index in resolving list of resolved address.
+ */
+int
+ble_hw_resolv_list_match(void)
+{
+ return -1;
+}
+#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/native/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/native/src/ble_phy.c b/hw/drivers/nimble/native/src/ble_phy.c
new file mode 100644
index 0000000..0f1ef5a
--- /dev/null
+++ b/hw/drivers/nimble/native/src/ble_phy.c
@@ -0,0 +1,603 @@
+/**
+ * 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 <string.h>
+#include <assert.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "ble/xcvr.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "controller/ble_phy.h"
+#include "controller/ble_ll.h"
+
+/* BLE PHY data structure */
+struct ble_phy_obj
+{
+ uint8_t phy_stats_initialized;
+ int8_t phy_txpwr_dbm;
+ uint8_t phy_chan;
+ uint8_t phy_state;
+ uint8_t phy_transition;
+ uint8_t phy_rx_started;
+ uint8_t phy_encrypted;
+ uint8_t phy_privacy;
+ uint8_t phy_tx_pyld_len;
+ uint32_t phy_aar_scratch;
+ uint32_t phy_access_address;
+ struct ble_mbuf_hdr rxhdr;
+ void *txend_arg;
+ uint8_t *rxdptr;
+ ble_phy_tx_end_func txend_cb;
+};
+struct ble_phy_obj g_ble_phy_data;
+
+/* Statistics */
+struct ble_phy_statistics
+{
+ uint32_t tx_good;
+ uint32_t tx_fail;
+ uint32_t tx_late;
+ uint32_t tx_bytes;
+ uint32_t rx_starts;
+ uint32_t rx_aborts;
+ uint32_t rx_valid;
+ uint32_t rx_crc_err;
+ uint32_t phy_isrs;
+ uint32_t radio_state_errs;
+ uint32_t no_bufs;
+};
+
+struct ble_phy_statistics g_ble_phy_stats;
+
+/* XCVR object to emulate transceiver */
+struct xcvr_data
+{
+ uint32_t irq_status;
+};
+static struct xcvr_data g_xcvr_data;
+
+#define BLE_XCVR_IRQ_F_RX_START (0x00000001)
+#define BLE_XCVR_IRQ_F_RX_END (0x00000002)
+#define BLE_XCVR_IRQ_F_TX_START (0x00000004)
+#define BLE_XCVR_IRQ_F_TX_END (0x00000008)
+#define BLE_XCVR_IRQ_F_BYTE_CNTR (0x00000010)
+
+/* "Rail" power level if outside supported range */
+#define BLE_XCVR_TX_PWR_MAX_DBM (30)
+#define BLE_XCVR_TX_PWR_MIN_DBM (-20)
+
+/* Statistics */
+STATS_SECT_START(ble_phy_stats)
+ STATS_SECT_ENTRY(phy_isrs)
+ STATS_SECT_ENTRY(tx_good)
+ STATS_SECT_ENTRY(tx_fail)
+ STATS_SECT_ENTRY(tx_late)
+ STATS_SECT_ENTRY(tx_bytes)
+ STATS_SECT_ENTRY(rx_starts)
+ STATS_SECT_ENTRY(rx_aborts)
+ STATS_SECT_ENTRY(rx_valid)
+ STATS_SECT_ENTRY(rx_crc_err)
+ STATS_SECT_ENTRY(rx_late)
+ STATS_SECT_ENTRY(no_bufs)
+ STATS_SECT_ENTRY(radio_state_errs)
+ STATS_SECT_ENTRY(rx_hw_err)
+ STATS_SECT_ENTRY(tx_hw_err)
+STATS_SECT_END
+STATS_SECT_DECL(ble_phy_stats) ble_phy_stats;
+
+STATS_NAME_START(ble_phy_stats)
+ STATS_NAME(ble_phy_stats, phy_isrs)
+ STATS_NAME(ble_phy_stats, tx_good)
+ STATS_NAME(ble_phy_stats, tx_fail)
+ STATS_NAME(ble_phy_stats, tx_late)
+ STATS_NAME(ble_phy_stats, tx_bytes)
+ STATS_NAME(ble_phy_stats, rx_starts)
+ STATS_NAME(ble_phy_stats, rx_aborts)
+ STATS_NAME(ble_phy_stats, rx_valid)
+ STATS_NAME(ble_phy_stats, rx_crc_err)
+ STATS_NAME(ble_phy_stats, rx_late)
+ STATS_NAME(ble_phy_stats, no_bufs)
+ STATS_NAME(ble_phy_stats, radio_state_errs)
+ STATS_NAME(ble_phy_stats, rx_hw_err)
+ STATS_NAME(ble_phy_stats, tx_hw_err)
+STATS_NAME_END(ble_phy_stats)
+
+/* XXX: TODO:
+
+ * 1) Test the following to make sure it works: suppose an event is already
+ * set to 1 and the interrupt is not enabled. What happens if you enable the
+ * interrupt with the event bit already set to 1
+ * 2) how to deal with interrupts?
+ */
+static uint32_t
+ble_xcvr_get_irq_status(void)
+{
+ return g_xcvr_data.irq_status;
+}
+
+static void
+ble_xcvr_clear_irq(uint32_t mask)
+{
+ g_xcvr_data.irq_status &= ~mask;
+}
+
+/**
+ * Copies the data from the phy receive buffer into a mbuf chain.
+ *
+ * @param dptr Pointer to receive buffer
+ * @param rxpdu Pointer to already allocated mbuf chain
+ *
+ * NOTE: the packet header already has the total mbuf length in it. The
+ * lengths of the individual mbufs are not set prior to calling.
+ *
+ */
+void
+ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
+{
+ uint16_t rem_bytes;
+ uint16_t mb_bytes;
+ uint16_t copylen;
+ uint32_t *dst;
+ uint32_t *src;
+ struct os_mbuf *m;
+ struct ble_mbuf_hdr *ble_hdr;
+ struct os_mbuf_pkthdr *pkthdr;
+
+ /* Better be aligned */
+ assert(((uint32_t)dptr & 3) == 0);
+
+ pkthdr = OS_MBUF_PKTHDR(rxpdu);
+ rem_bytes = pkthdr->omp_len;
+
+ /* Fill in the mbuf pkthdr first. */
+ dst = (uint32_t *)(rxpdu->om_data);
+ src = (uint32_t *)dptr;
+
+ mb_bytes = (rxpdu->om_omp->omp_databuf_len - rxpdu->om_pkthdr_len - 4);
+ copylen = min(mb_bytes, rem_bytes);
+ copylen &= 0xFFFC;
+ rem_bytes -= copylen;
+ mb_bytes -= copylen;
+ rxpdu->om_len = copylen;
+ while (copylen > 0) {
+ *dst = *src;
+ ++dst;
+ ++src;
+ copylen -= 4;
+ }
+
+ /* Copy remaining bytes */
+ m = rxpdu;
+ while (rem_bytes > 0) {
+ /* If there are enough bytes in the mbuf, copy them and leave */
+ if (rem_bytes <= mb_bytes) {
+ memcpy(m->om_data + m->om_len, src, rem_bytes);
+ m->om_len += rem_bytes;
+ break;
+ }
+
+ m = SLIST_NEXT(m, om_next);
+ assert(m != NULL);
+
+ mb_bytes = m->om_omp->omp_databuf_len;
+ copylen = min(mb_bytes, rem_bytes);
+ copylen &= 0xFFFC;
+ rem_bytes -= copylen;
+ mb_bytes -= copylen;
+ m->om_len = copylen;
+ dst = (uint32_t *)m->om_data;
+ while (copylen > 0) {
+ *dst = *src;
+ ++dst;
+ ++src;
+ copylen -= 4;
+ }
+ }
+
+ /* Copy ble header */
+ ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
+ memcpy(ble_hdr, &g_ble_phy_data.rxhdr, sizeof(struct ble_mbuf_hdr));
+}
+
+void
+ble_phy_isr(void)
+{
+ int rc;
+ uint8_t crcok;
+ uint8_t transition;
+ uint32_t irq_en;
+ struct ble_mbuf_hdr *ble_hdr;
+
+ /* Check for disabled event. This only happens for transmits now */
+ irq_en = ble_xcvr_get_irq_status();
+ if (irq_en & BLE_XCVR_IRQ_F_TX_END) {
+
+ /* Better be in TX state! */
+ assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX);
+ ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_TX_END);
+
+ transition = g_ble_phy_data.phy_transition;
+ if (transition == BLE_PHY_TRANSITION_TX_RX) {
+ /* Disable the phy */
+ /* XXX: count no bufs? */
+ ble_phy_disable();
+ } else {
+ /* Better not be going from rx to tx! */
+ assert(transition == BLE_PHY_TRANSITION_NONE);
+ }
+ }
+
+ /* We get this if we have started to receive a frame */
+ if (irq_en & BLE_XCVR_IRQ_F_RX_START) {
+
+ ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_RX_START);
+
+ /* Call Link Layer receive start function */
+ rc = ble_ll_rx_start(g_ble_phy_data.rxdptr, g_ble_phy_data.phy_chan,
+ &g_ble_phy_data.rxhdr);
+ if (rc >= 0) {
+ /* XXX: set rx end enable isr */
+ } else {
+ /* Disable PHY */
+ ble_phy_disable();
+ irq_en = 0;
+ ++g_ble_phy_stats.rx_aborts;
+ }
+
+ /* Count rx starts */
+ ++g_ble_phy_stats.rx_starts;
+ }
+
+ /* Receive packet end (we dont enable this for transmit) */
+ if (irq_en & BLE_XCVR_IRQ_F_RX_END) {
+
+ ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_RX_END);
+
+ /* Construct BLE header before handing up */
+ ble_hdr = &g_ble_phy_data.rxhdr;
+ ble_hdr->rxinfo.flags = 0;
+ ble_hdr->rxinfo.rssi = -77; /* XXX: dummy rssi */
+ ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
+
+ /* Count PHY crc errors and valid packets */
+ crcok = 1;
+ if (!crcok) {
+ ++g_ble_phy_stats.rx_crc_err;
+ } else {
+ ++g_ble_phy_stats.rx_valid;
+ ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK;
+ }
+
+ /* Call Link Layer receive payload function */
+ rc = ble_ll_rx_end(g_ble_phy_data.rxdptr, ble_hdr);
+ if (rc < 0) {
+ /* Disable the PHY. */
+ ble_phy_disable();
+ }
+ }
+
+ /* Count # of interrupts */
+ ++g_ble_phy_stats.phy_isrs;
+}
+
+/**
+ * ble phy init
+ *
+ * Initialize the PHY. This is expected to be called once.
+ *
+ * @return int 0: success; PHY error code otherwise
+ */
+int
+ble_phy_init(void)
+{
+ /* Set phy channel to an invalid channel so first set channel works */
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+ g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
+
+ /* XXX: emulate ISR? */
+
+ return 0;
+}
+
+int
+ble_phy_rx(void)
+{
+ /* Check radio state */
+ if (ble_phy_state_get() != BLE_PHY_STATE_IDLE) {
+ ble_phy_disable();
+ ++g_ble_phy_stats.radio_state_errs;
+ return BLE_PHY_ERR_RADIO_STATE;
+ }
+
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_RX;
+
+ return 0;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
+/**
+ * Called to enable encryption at the PHY. Note that this state will persist
+ * in the PHY; in other words, if you call this function you have to call
+ * disable so that future PHY transmits/receives will not be encrypted.
+ *
+ * @param pkt_counter
+ * @param iv
+ * @param key
+ * @param is_master
+ */
+void
+ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key,
+ uint8_t is_master)
+{
+}
+
+void
+ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir)
+{
+}
+
+void
+ble_phy_encrypt_disable(void)
+{
+}
+#endif
+
+void
+ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
+{
+ /* Set transmit end callback and arg */
+ g_ble_phy_data.txend_cb = txend_cb;
+ g_ble_phy_data.txend_arg = arg;
+}
+
+/**
+ * Called to set the start time of a transmission.
+ *
+ * This function is called to set the start time when we are not going from
+ * rx to tx automatically.
+ *
+ * NOTE: care must be taken when calling this function. The channel should
+ * already be set.
+ *
+ * @param cputime
+ *
+ * @return int
+ */
+int
+ble_phy_tx_set_start_time(uint32_t cputime)
+{
+ return 0;
+}
+
+/**
+ * Called to set the start time of a reception
+ *
+ * This function acts a bit differently than transmit. If we are late getting
+ * here we will still attempt to receive.
+ *
+ * NOTE: care must be taken when calling this function. The channel should
+ * already be set.
+ *
+ * @param cputime
+ *
+ * @return int
+ */
+int
+ble_phy_rx_set_start_time(uint32_t cputime)
+{
+ return 0;
+}
+
+
+int
+ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
+{
+ int rc;
+ uint32_t state;
+
+ /* Better have a pdu! */
+ assert(txpdu != NULL);
+
+
+ if (ble_phy_state_get() != BLE_PHY_STATE_IDLE) {
+ ble_phy_disable();
+ ++g_ble_phy_stats.radio_state_errs;
+ return BLE_PHY_ERR_RADIO_STATE;
+ }
+
+ /* Select tx address */
+ if (g_ble_phy_data.phy_chan < BLE_PHY_NUM_DATA_CHANS) {
+ /* XXX: fix this */
+ assert(0);
+ } else {
+ }
+
+
+ /* Set the PHY transition */
+ g_ble_phy_data.phy_transition = end_trans;
+
+ /* Make sure transceiver in correct state */
+ state = BLE_PHY_STATE_TX;
+ if (state == BLE_PHY_STATE_TX) {
+ /* Set phy state to transmitting and count packet statistics */
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
+ ++g_ble_phy_stats.tx_good;
+ g_ble_phy_stats.tx_bytes += OS_MBUF_PKTHDR(txpdu)->omp_len +
+ BLE_LL_PDU_HDR_LEN;
+ rc = BLE_ERR_SUCCESS;
+ } else {
+ /* Frame failed to transmit */
+ ++g_ble_phy_stats.tx_fail;
+ ble_phy_disable();
+ rc = BLE_PHY_ERR_RADIO_STATE;
+ }
+
+ return rc;
+}
+
+/**
+ * ble phy txpwr set
+ *
+ * Set the transmit output power (in dBm).
+ *
+ * NOTE: If the output power specified is within the BLE limits but outside
+ * the chip limits, we "rail" the power level so we dont exceed the min/max
+ * chip values.
+ *
+ * @param dbm Power output in dBm.
+ *
+ * @return int 0: success; anything else is an error
+ */
+int
+ble_phy_txpwr_set(int dbm)
+{
+ /* Check valid range */
+ assert(dbm <= BLE_PHY_MAX_PWR_DBM);
+
+ /* "Rail" power level if outside supported range */
+ if (dbm > BLE_XCVR_TX_PWR_MAX_DBM) {
+ dbm = BLE_XCVR_TX_PWR_MAX_DBM;
+ } else {
+ if (dbm < BLE_XCVR_TX_PWR_MIN_DBM) {
+ dbm = BLE_XCVR_TX_PWR_MIN_DBM;
+ }
+ }
+
+ g_ble_phy_data.phy_txpwr_dbm = dbm;
+
+ return 0;
+}
+
+/**
+ * ble phy txpwr get
+ *
+ * Get the transmit power.
+ *
+ * @return int The current PHY transmit power, in dBm
+ */
+int
+ble_phy_txpwr_get(void)
+{
+ return g_ble_phy_data.phy_txpwr_dbm;
+}
+
+/**
+ * ble phy setchan
+ *
+ * Sets the logical frequency of the transceiver. The input parameter is the
+ * BLE channel index (0 to 39, inclusive). The NRF52 frequency register
+ * works like this: logical frequency = 2400 + FREQ (MHz).
+ *
+ * Thus, to get a logical frequency of 2402 MHz, you would program the
+ * FREQUENCY register to 2.
+ *
+ * @param chan This is the Data Channel Index or Advertising Channel index
+ *
+ * @return int 0: success; PHY error code otherwise
+ */
+int
+ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
+{
+ assert(chan < BLE_PHY_NUM_CHANS);
+
+ /* Check for valid channel range */
+ if (chan >= BLE_PHY_NUM_CHANS) {
+ return BLE_PHY_ERR_INV_PARAM;
+ }
+
+ /* Set current access address */
+ if (chan < BLE_PHY_NUM_DATA_CHANS) {
+ g_ble_phy_data.phy_access_address = access_addr;
+ } else {
+ g_ble_phy_data.phy_access_address = BLE_ACCESS_ADDR_ADV;
+ }
+ g_ble_phy_data.phy_chan = chan;
+
+ return 0;
+}
+
+/**
+ * Disable the PHY. This will do the following:
+ * -> Turn off all phy interrupts.
+ * -> Disable internal shortcuts.
+ * -> Disable the radio.
+ * -> Sets phy state to idle.
+ */
+void
+ble_phy_disable(void)
+{
+ g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
+}
+
+/* Gets the current access address */
+uint32_t ble_phy_access_addr_get(void)
+{
+ return g_ble_phy_data.phy_access_address;
+}
+
+/**
+ * Return the phy state
+ *
+ * @return int The current PHY state.
+ */
+int
+ble_phy_state_get(void)
+{
+ return g_ble_phy_data.phy_state;
+}
+
+/**
+ * Called to see if a reception has started
+ *
+ * @return int
+ */
+int
+ble_phy_rx_started(void)
+{
+ return g_ble_phy_data.phy_rx_started;
+}
+
+/**
+ * Called to return the maximum data pdu payload length supported by the
+ * phy. For this chip, if encryption is enabled, the maximum payload is 27
+ * bytes.
+ *
+ * @return uint8_t Maximum data channel PDU payload size supported
+ */
+uint8_t
+ble_phy_max_data_pdu_pyld(void)
+{
+ return BLE_LL_DATA_PDU_MAX_PYLD;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+void
+ble_phy_resolv_list_enable(void)
+{
+ g_ble_phy_data.phy_privacy = 1;
+}
+
+void
+ble_phy_resolv_list_disable(void)
+{
+ g_ble_phy_data.phy_privacy = 0;
+}
+#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/nrf51/include/ble/xcvr.h
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf51/include/ble/xcvr.h b/hw/drivers/nimble/nrf51/include/ble/xcvr.h
new file mode 100644
index 0000000..7041d8d
--- /dev/null
+++ b/hw/drivers/nimble/nrf51/include/ble/xcvr.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 H_BLE_XCVR_
+#define H_BLE_XCVR_
+
+/* Transceiver specific defintions */
+#define XCVR_RX_START_DELAY_USECS (140)
+#define XCVR_TX_START_DELAY_USECS (140)
+#define XCVR_PROC_DELAY_USECS (100)
+#define XCVR_TX_SCHED_DELAY_USECS \
+ (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+#define XCVR_RX_SCHED_DELAY_USECS \
+ (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+
+/*
+ * Define HW whitelist size. This is the total possible whitelist size;
+ * not necessarily the size that will be used (may be smaller)
+ */
+#define BLE_HW_WHITE_LIST_SIZE (8)
+
+#endif /* H_BLE_XCVR_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/nrf51/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf51/pkg.yml b/hw/drivers/nimble/nrf51/pkg.yml
new file mode 100644
index 0000000..6a600cd
--- /dev/null
+++ b/hw/drivers/nimble/nrf51/pkg.yml
@@ -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.
+#
+
+pkg.name: hw/drivers/nimble/nrf51
+pkg.description: BLE driver for nRF51 systems.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - ble
+ - bluetooth
+
+pkg.apis: ble_driver
+pkg.deps:
+ - net/nimble
+ - net/nimble/controller
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/hw/drivers/nimble/nrf51/src/ble_hw.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf51/src/ble_hw.c b/hw/drivers/nimble/nrf51/src/ble_hw.c
new file mode 100644
index 0000000..259bd05
--- /dev/null
+++ b/hw/drivers/nimble/nrf51/src/ble_hw.c
@@ -0,0 +1,432 @@
+/**
+ * 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 <assert.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "ble/xcvr.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "nrf51_bitfields.h"
+#include "controller/ble_hw.h"
+#include "bsp/cmsis_nvic.h"
+
+/* Total number of resolving list elements */
+#define BLE_HW_RESOLV_LIST_SIZE (16)
+
+/* We use this to keep track of which entries are set to valid addresses */
+static uint8_t g_ble_hw_whitelist_mask;
+
+/* Random number generator isr callback */
+ble_rng_isr_cb_t g_ble_rng_isr_cb;
+
+/* If LL privacy is enabled, allocate memory for AAR */
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
+
+/* The NRF51 supports up to 16 IRK entries */
+#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16)
+#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
+#else
+#define NRF_IRK_LIST_ENTRIES (16)
+#endif
+
+/* NOTE: each entry is 16 bytes long. */
+uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4];
+
+/* Current number of IRK entries */
+uint8_t g_nrf_num_irks;
+
+#endif
+
+/**
+ * Clear the whitelist
+ *
+ * @return int
+ */
+void
+ble_hw_whitelist_clear(void)
+{
+ NRF_RADIO->DACNF = 0;
+ g_ble_hw_whitelist_mask = 0;
+}
+
+/**
+ * Add a device to the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
+{
+ int i;
+ uint32_t mask;
+
+ /* Find first ununsed device address match element */
+ mask = 0x01;
+ for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
+ if ((mask & g_ble_hw_whitelist_mask) == 0) {
+ NRF_RADIO->DAB[i] = le32toh(addr);
+ NRF_RADIO->DAP[i] = le16toh(addr + 4);
+ if (addr_type == BLE_ADDR_TYPE_RANDOM) {
+ NRF_RADIO->DACNF |= (mask << 8);
+ }
+ g_ble_hw_whitelist_mask |= mask;
+ return BLE_ERR_SUCCESS;
+ }
+ mask <<= 1;
+ }
+
+ return BLE_ERR_MEM_CAPACITY;
+}
+
+/**
+ * Remove a device from the hw whitelist
+ *
+ * @param addr
+ * @param addr_type
+ *
+ */
+void
+ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
+{
+ int i;
+ uint8_t cfg_addr;
+ uint16_t dap;
+ uint16_t txadd;
+ uint32_t dab;
+ uint32_t mask;
+
+ /* Find first ununsed device address match element */
+ dab = le32toh(addr);
+ dap = le16toh(addr + 4);
+ txadd = NRF_RADIO->DACNF >> 8;
+ mask = 0x01;
+ for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
+ if (mask & g_ble_hw_whitelist_mask) {
+ if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) {
+ cfg_addr = txadd & mask;
+ if (addr_type == BLE_ADDR_TYPE_RANDOM) {
+ if (cfg_addr != 0) {
+ break;
+ }
+ } else {
+ if (cfg_addr == 0) {
+ break;
+ }
+ }
+ }
+ }
+ mask <<= 1;
+ }
+
+ if (i < BLE_HW_WHITE_LIST_SIZE) {
+ g_ble_hw_whitelist_mask &= ~mask;
+ NRF_RADIO->DACNF &= ~mask;
+ }
+}
+
+/**
+ * Returns the size of the whitelist in HW
+ *
+ * @return int Number of devices allowed in whitelist
+ */
+uint8_t
+ble_hw_whitelist_size(void)
+{
+ return BLE_HW_WHITE_LIST_SIZE;
+}
+
+/**
+ * Enable the whitelisted devices
+ */
+void
+ble_hw_whitelist_enable(void)
+{
+ /* Enable the configured device addresses */
+ NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask;
+}
+
+/**
+ * Disables the whitelisted devices
+ */
+void
+ble_hw_whitelist_disable(void)
+{
+ /* Disable all whitelist devices */
+ NRF_RADIO->DACNF &= 0x0000ff00;
+}
+
+/**
+ * Boolean function which returns true ('1') if there is a match on the
+ * whitelist.
+ *
+ * @return int
+ */
+int
+ble_hw_whitelist_match(void)
+{
+ return (int)NRF_RADIO->EVENTS_DEVMATCH;
+}
+
+/* Encrypt data */
+int
+ble_hw_encrypt_block(struct ble_encryption_block *ecb)
+{
+ int rc;
+ uint32_t end;
+ uint32_t err;
+
+ /* Stop ECB */
+ NRF_ECB->TASKS_STOPECB = 1;
+ /* XXX: does task stop clear these counters? Anyway to do this quicker? */
+ NRF_ECB->EVENTS_ENDECB = 0;
+ NRF_ECB->EVENTS_ERRORECB = 0;
+ NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
+
+ /* Start ECB */
+ NRF_ECB->TASKS_STARTECB = 1;
+
+ /* Wait till error or done */
+ rc = 0;
+ while (1) {
+ end = NRF_ECB->EVENTS_ENDECB;
+ err = NRF_ECB->EVENTS_ERRORECB;
+ if (end || err) {
+ if (err) {
+ rc = -1;
+ }
+ break;
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * Random number generator ISR.
+ */
+static void
+ble_rng_isr(void)
+{
+ uint8_t rnum;
+
+ /* No callback? Clear and disable interrupts */
+ if (g_ble_rng_isr_cb == NULL) {
+ NRF_RNG->INTENCLR = 1;
+ NRF_RNG->EVENTS_VALRDY = 0;
+ (void)NRF_RNG->SHORTS;
+ return;
+ }
+
+ /* If there is a value ready grab it */
+ if (NRF_RNG->EVENTS_VALRDY) {
+ NRF_RNG->EVENTS_VALRDY = 0;
+ rnum = (uint8_t)NRF_RNG->VALUE;
+ (*g_ble_rng_isr_cb)(rnum);
+ }
+}
+
+/**
+ * Initialize the random number generator
+ *
+ * @param cb
+ * @param bias
+ *
+ * @return int
+ */
+int
+ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
+{
+ /* Set bias */
+ if (bias) {
+ NRF_RNG->CONFIG = 1;
+ } else {
+ NRF_RNG->CONFIG = 0;
+ }
+
+ /* If we were passed a function pointer we need to enable the interrupt */
+ if (cb != NULL) {
+ NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+ NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
+ NVIC_EnableIRQ(RNG_IRQn);
+ g_ble_rng_isr_cb = cb;
+ }
+
+ return 0;
+}
+
+/**
+ * Start the random number generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_start(void)
+{
+ os_sr_t sr;
+
+ /* No need for interrupt if there is no callback */
+ OS_ENTER_CRITICAL(sr);
+ if (NRF_RNG->TASKS_START == 0) {
+ NRF_RNG->EVENTS_VALRDY = 0;
+ if (g_ble_rng_isr_cb) {
+ NRF_RNG->INTENSET = 1;
+ }
+ NRF_RNG->TASKS_START = 1;
+ }
+ OS_EXIT_CRITICAL(sr);
+
+ return 0;
+}
+
+/**
+ * Stop the random generator
+ *
+ * @return int
+ */
+int
+ble_hw_rng_stop(void)
+{
+ os_sr_t sr;
+
+ /* No need for interrupt if there is no callback */
+ OS_ENTER_CRITICAL(sr);
+ NRF_RNG->INTENCLR = 1;
+ NRF_RNG->TASKS_STOP = 1;
+ NRF_RNG->EVENTS_VALRDY = 0;
+ OS_EXIT_CRITICAL(sr);
+
+ return 0;
+}
+
+/**
+ * Read the random number generator.
+ *
+ * @return uint8_t
+ */
+uint8_t
+ble_hw_rng_read(void)
+{
+ uint8_t rnum;
+
+ /* Wait for a sample */
+ while (NRF_RNG->EVENTS_VALRDY == 0) {
+ }
+
+ NRF_RNG->EVENTS_VALRDY = 0;
+ rnum = (uint8_t)NRF_RNG->VALUE;
+
+ return rnum;
+}
+
+#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY))
+/**
+ * Clear the resolving list
+ *
+ * @return int
+ */
+void
+ble_hw_resolv_list_clear(void)
+{
+ g_nrf_num_irks = 0;
+}
+
+/**
+ * Add a device to the hw resolving list
+ *
+ * @param irk Pointer to IRK to add
+ *
+ * @return int 0: success, BLE error code otherwise
+ */
+int
+ble_hw_resolv_list_add(uint8_t *irk)
+{
+ uint32_t *nrf_entry;
+
+ /* Find first ununsed device address match element */
+ if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) {
+ return BLE_ERR_MEM_CAPACITY;
+ }
+
+ /* Copy into irk list */
+ nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks];
+ memcpy(nrf_entry, irk, 16);
+
+ /* Add to total */
+ ++g_nrf_num_irks;
+ return BLE_ERR_SUCCESS;
+}
+
+/**
+ * Remove a device from the hw resolving list
+ *
+ * @param index Index of IRK to remove
+ */
+void
+ble_hw_resolv_list_rmv(int index)
+{
+ uint32_t *irk_entry;
+
+ if (index < g_nrf_num_irks) {
+ --g_nrf_num_irks;
+ irk_entry = &g_nrf_irk_list[index];
+ if (g_nrf_num_irks > index) {
+ memmove(irk_entry, irk_entry + 4, g_nrf_num_irks - index);
+ }
+ }
+}
+
+/**
+ * Returns the size of the resolving list. NOTE: this returns the maximum
+ * allowable entries in the HW. Configuration options may limit this.
+ *
+ * @return int Number of devices allowed in resolving list
+ */
+uint8_t
+ble_hw_resolv_list_size(void)
+{
+ return BLE_HW_RESOLV_LIST_SIZE;
+}
+
+/**
+ * Called to determine if the address received was resolved.
+ *
+ * @return int Negative values indicate unresolved address; positive values
+ * indicate index in resolving list of resolved address.
+ */
+int
+ble_hw_resolv_list_match(void)
+{
+ uint32_t index;
+
+ if (NRF_AAR->EVENTS_END) {
+ if (NRF_AAR->EVENTS_RESOLVED) {
+ index = NRF_AAR->STATUS;
+ return (int)index;
+ }
+ }
+
+ return -1;
+}
+#endif