jacobrosenthal commented on a change in pull request #763: [WIP - Do not merge] 
Integrate nrfx
URL: https://github.com/apache/mynewt-core/pull/763#discussion_r167265955
 
 

 ##########
 File path: hw/drivers/adc/adc_nrf51/src/adc_nrf51.c
 ##########
 @@ -0,0 +1,409 @@
+/*
+ * 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 <nrfx.h>
+#include <nrfx_adc.h>
+
+
+#include "adc_nrf51/adc_nrf51.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;
+
+static struct adc_dev *global_adc_dev;
+
+static nrfx_adc_config_t *global_adc_config;
+static struct nrf51_adc_dev_cfg *init_adc_config;
+
+static struct adc_chan_config nrf51_adc_chans[NRF_ADC_CHANNEL_COUNT];
+static nrfx_adc_channel_t *nrf_adc_chan;
+
+static void
+nrf51_adc_event_handler(const nrfx_adc_evt_t *event)
+{
+    nrfx_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 == NRFX_ADC_EVT_DONE);
+
+    done_ev = (nrfx_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 must be a nrfx_adc_config_t
+ *             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;
+    nrfx_adc_config_t *cfg;
+    int rc;
+
+    if (arg == NULL) {
+        rc = OS_EINVAL;
+        goto err;
+    }
+
+    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 = (nrfx_adc_config_t *)arg;
+    rc = nrfx_adc_init(cfg, nrf51_adc_event_handler);
+    if (rc != NRFX_SUCCESS) {
+        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;
+
+    nrfx_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 nrfx_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)
+{
+    int rc;
+    nrfx_adc_channel_config_t *cc_cfg;
+    int reference;
+    uint16_t refmv;
+    uint8_t res;
+
+    if (global_adc_config == NULL) {
+        rc = OS_ERROR;
+        goto err;
+    }
+
+    //store nrf_adc_chan for nrf51_adc_read_channel
+    nrf_adc_chan = cfgdata;
+
+    nrfx_adc_channel_enable(nrf_adc_chan);
+
+    // they play shenanigans storing the reference bit fields so we have to as 
well
+    cc_cfg = &nrf_adc_chan->config.config;
+    reference = cc_cfg->reference | (cc_cfg->external_reference << 
ADC_CONFIG_EXTREFSEL_Pos);
+
+    /* Set the resolution and reference voltage for this channel to
+    * enable conversion functions.
+    */
+    switch (cc_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 (reference) {
+        case NRF_ADC_CONFIG_REF_VBG:
+            refmv = 1200; /* 1.2V for NRF51 */
+            break;
+        case NRF_ADC_CONFIG_REF_EXT_REF0:
+            refmv = init_adc_config->nadc_refmv0;
+            break;
+        case NRF_ADC_CONFIG_REF_EXT_REF1:
+            refmv = init_adc_config->nadc_refmv1;
+            break;
+        case NRF_ADC_CONFIG_REF_SUPPLY_ONE_HALF:
+            refmv = init_adc_config->nadc_refmv_vdd / 2;
+            break;
+        case NRF_ADC_CONFIG_REF_SUPPLY_ONE_THIRD:
+            refmv = init_adc_config->nadc_refmv_vdd / 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;
+    dev->ad_chans[cnum].c_cnum = cnum;
+
+    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;
+
+    if (dev == NULL || buf1 == NULL) {
+        rc = OS_EINVAL;
+        goto err;
+    }
+
+    /* Convert overall buffer length, into a total number of samples which
+     * Nordic APIs expect.
+     */
+    buf_len /= sizeof(nrf_adc_value_t);
+
+    rc = nrfx_adc_buffer_convert((nrf_adc_value_t *) buf1, buf_len);
+    if (rc != NRFX_SUCCESS) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+//WHY DOES THIS EXIST! why doesnt it work without it!
 
 Review comment:
   Heh. I dont understand why calling nrfx_adc_buffer_convert would 'release' 
the buffer, but when I remove this it breaks....

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to