This is an automated email from the ASF dual-hosted git repository. janc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 55dc8b7cc85658da7950d987fa80a6c2ea09d71b Author: Miguel Azevedo <miguella...@gmail.com> AuthorDate: Thu Feb 13 03:35:56 2020 +0000 hw/drivers/adc: Update nrf52_adc driver for nrfx 2.0.0 --- .../adc/adc_nrf52/include/adc_nrf52/adc_nrf52.h | 63 +- hw/drivers/adc/adc_nrf52/src/adc_nrf52.c | 590 +++++++++++++------ hw/mcu/nordic/nrf52xxx/src/nrfx_saadc_mod.c | 651 --------------------- 3 files changed, 482 insertions(+), 822 deletions(-) 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 index edd0938..52f8efe 100644 --- a/hw/drivers/adc/adc_nrf52/include/adc_nrf52/adc_nrf52.h +++ b/hw/drivers/adc/adc_nrf52/include/adc_nrf52/adc_nrf52.h @@ -26,8 +26,67 @@ extern "C" { #endif +typedef enum { + ADC_RESOLUTION_8BIT = 0, + ADC_RESOLUTION_10BIT, + ADC_RESOLUTION_12BIT, + ADC_RESOLUTION_14BIT +} adc_resolution_t; + +typedef enum { + ADC_OVERSAMPLE_DISABLED = 0, + ADC_OVERSAMPLE_2X, + ADC_OVERSAMPLE_4X, + ADC_OVERSAMPLE_8X, + ADC_OVERSAMPLE_16X, + ADC_OVERSAMPLE_32X, + ADC_OVERSAMPLE_64X, + ADC_OVERSAMPLE_128X, + ADC_OVERSAMPLE_256X +} adc_oversample_t; + struct nrf52_adc_dev_cfg { - uint16_t nadc_refmv; /* reference VDD in mV */ + uint16_t nadc_refmv; /* Reference VDD in mV */ +}; + +struct adc_dev_cfg { + adc_resolution_t resolution; + adc_oversample_t oversample; /* Only works on single channel mode */ + bool calibrate; /* Calibrate before sampling */ +}; + +typedef enum { + ADC_REFERENCE_INTERNAL = 0, + ADC_REFERENCE_VDD_DIV_4 +} adc_ref_t; + +typedef enum { + ADC_GAIN1_6 = 0, + ADC_GAIN1_5, + ADC_GAIN1_4, + ADC_GAIN1_3, + ADC_GAIN1_2, + ADC_GAIN1, + ADC_GAIN2, + ADC_GAIN4 +} adc_gain_t; + +typedef enum { + ADC_ACQTIME_3US = 0, + ADC_ACQTIME_5US, + ADC_ACQTIME_10US, + ADC_ACQTIME_15US, + ADC_ACQTIME_20US, + ADC_ACQTIME_40US +} adc_acq_time_t; + +struct adc_chan_cfg { + adc_gain_t gain; + adc_ref_t reference; + adc_acq_time_t acq_time; + uint8_t pin; + bool differential; + uint8_t pin_negative; }; int nrf52_adc_dev_init(struct os_dev *, void *); @@ -36,4 +95,4 @@ int nrf52_adc_dev_init(struct os_dev *, void *); } #endif -#endif /* __ADC_H__ */ +#endif /* __ADC_NRF52_H__ */ diff --git a/hw/drivers/adc/adc_nrf52/src/adc_nrf52.c b/hw/drivers/adc/adc_nrf52/src/adc_nrf52.c index 85ddffc..44cb266 100644 --- a/hw/drivers/adc/adc_nrf52/src/adc_nrf52.c +++ b/hw/drivers/adc/adc_nrf52/src/adc_nrf52.c @@ -24,9 +24,7 @@ #include <mcu/cmsis_nvic.h> /* Nordic headers */ -#include <nrfx.h> #include <nrf_saadc.h> -#include <nrfx_saadc.h> #include "adc_nrf52/adc_nrf52.h" @@ -36,50 +34,102 @@ struct nrf52_saadc_stats { }; static struct nrf52_saadc_stats nrf52_saadc_stats; +static struct nrf52_adc_dev_cfg *init_cfg; static struct adc_dev *global_adc_dev; -static nrfx_saadc_config_t *global_adc_config; -static struct nrf52_adc_dev_cfg *init_adc_config; +static struct adc_chan_config nrf52_adc_chans[SAADC_CH_NUM]; -static uint8_t nrf52_adc_chans[NRF_SAADC_CHANNEL_COUNT * sizeof(struct adc_chan_config)]; +struct nrf52_adc_chan { + nrf_saadc_input_t pin_p; + nrf_saadc_input_t pin_n; + nrf_saadc_channel_config_t nrf_chan; +}; -static void -nrf52_saadc_event_handler(const nrfx_saadc_evt_t *event) -{ - nrfx_saadc_done_evt_t *done_ev; - int rc; +struct nrf52_saadc_dev_global { + nrf_saadc_value_t *primary_buf; + nrf_saadc_value_t *secondary_buf; + uint16_t primary_size; + uint16_t secondary_size; + nrf_saadc_resolution_t resolution; + nrf_saadc_oversample_t oversample; + struct nrf52_adc_chan channels[SAADC_CH_NUM]; + bool calibrate; +}; - if (global_adc_dev == NULL || !global_adc_dev->ad_event_handler_func) { - ++nrf52_saadc_stats.saadc_events_failed; - return; - } +static struct nrf52_saadc_dev_global g_drv_instance; - ++nrf52_saadc_stats.saadc_events; +/** + * Initialize a channel with default/unconfigured values. + */ +static void +channel_unconf(int cnum) +{ + nrf_saadc_channel_config_t default_ch = { + .gain = NRF_SAADC_GAIN1_6, + .reference = NRF_SAADC_REFERENCE_INTERNAL, + .acq_time = NRF_SAADC_ACQTIME_10US, + .mode = NRF_SAADC_MODE_SINGLE_ENDED, + .burst = NRF_SAADC_BURST_DISABLED, + .resistor_p = NRF_SAADC_RESISTOR_DISABLED, + .resistor_n = NRF_SAADC_RESISTOR_DISABLED, + }; + + memcpy(&g_drv_instance.channels[cnum].nrf_chan, + &default_ch, + sizeof(nrf_saadc_channel_config_t)); + g_drv_instance.channels[cnum].pin_p = NRF_SAADC_INPUT_DISABLED; + g_drv_instance.channels[cnum].pin_n = NRF_SAADC_INPUT_DISABLED; + global_adc_dev->ad_chans[cnum].c_configured = 0; +} - switch (event->type) { - case NRFX_SAADC_EVT_DONE: - done_ev = (nrfx_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)); - break; - case NRFX_SAADC_EVT_CALIBRATEDONE: - rc = global_adc_dev->ad_event_handler_func(global_adc_dev, - global_adc_dev->ad_event_handler_arg, - ADC_EVENT_CALIBRATED, NULL, 0); - break; - default: - assert(0); - break; +/** + * Initialize a driver instance with default/unconfigured values. + */ +static void +init_instance_unconf(void) +{ + int cnum; + + g_drv_instance.primary_buf = NULL; + g_drv_instance.secondary_buf = NULL; + g_drv_instance.primary_size = 0; + g_drv_instance.secondary_size = 0; + g_drv_instance.resolution = NRF_SAADC_RESOLUTION_14BIT; + g_drv_instance.oversample = NRF_SAADC_OVERSAMPLE_DISABLED; + g_drv_instance.calibrate = false; + + for (cnum = 0; cnum < SAADC_CH_NUM; cnum++) { + channel_unconf(cnum); } +} - if (rc != 0) { - ++nrf52_saadc_stats.saadc_events_failed; +/** + * Unconfigures the device registers + */ +static void +clear_device_regs(void) +{ + int cnum; + nrf_saadc_channel_config_t default_ch = { + .gain = NRF_SAADC_GAIN1_6, + .reference = NRF_SAADC_REFERENCE_INTERNAL, + .acq_time = NRF_SAADC_ACQTIME_10US, + .mode = NRF_SAADC_MODE_SINGLE_ENDED, + .burst = NRF_SAADC_BURST_DISABLED, + .resistor_p = NRF_SAADC_RESISTOR_DISABLED, + .resistor_n = NRF_SAADC_RESISTOR_DISABLED, + }; + + nrf_saadc_int_disable(NRF_SAADC, NRF_SAADC_INT_ALL); + nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END); + nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STARTED); + + for (cnum = 0; cnum < SAADC_CH_NUM; cnum++) { + nrf_saadc_channel_init(NRF_SAADC, cnum, &default_ch); + nrf_saadc_channel_input_set(NRF_SAADC, cnum, NRF_SAADC_INPUT_DISABLED, + NRF_SAADC_INPUT_DISABLED); } } - /** * Open the NRF52 ADC device * @@ -90,7 +140,7 @@ nrf52_saadc_event_handler(const nrfx_saadc_evt_t *event) * 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 nrfx_saadc_config_t, to override the default + * it can be a adc_dev_cfg, to override the default * configuration. * * @return 0 on success, non-zero on failure. @@ -98,11 +148,10 @@ nrf52_saadc_event_handler(const nrfx_saadc_evt_t *event) static int nrf52_adc_open(struct os_dev *odev, uint32_t wait, void *arg) { - struct adc_dev *dev; int rc = 0; int unlock = 0; - - dev = (struct adc_dev *) odev; + struct adc_dev *dev = (struct adc_dev *) odev; + struct adc_dev_cfg *adc_config = (struct adc_dev_cfg *) arg; if (os_started()) { rc = os_mutex_pend(&dev->ad_lock, wait); @@ -113,24 +162,71 @@ nrf52_adc_open(struct os_dev *odev, uint32_t wait, void *arg) } if (++(dev->ad_ref_cnt) == 1) { - /* Initialize the device */ - rc = nrfx_saadc_init((nrfx_saadc_config_t *) arg, - nrf52_saadc_event_handler); - if (rc != NRFX_SUCCESS) { - goto err; - } - rc = 0; - + init_instance_unconf(); + NVIC_SetPriority(SAADC_IRQn, 0); + NVIC_EnableIRQ(SAADC_IRQn); global_adc_dev = dev; - global_adc_config = arg; + + if (adc_config) { + switch (adc_config->resolution) { + case ADC_RESOLUTION_8BIT: + g_drv_instance.resolution = NRF_SAADC_RESOLUTION_8BIT; + break; + case ADC_RESOLUTION_10BIT: + g_drv_instance.resolution = NRF_SAADC_RESOLUTION_10BIT; + break; + case ADC_RESOLUTION_12BIT: + g_drv_instance.resolution = NRF_SAADC_RESOLUTION_12BIT; + break; + case ADC_RESOLUTION_14BIT: + g_drv_instance.resolution = NRF_SAADC_RESOLUTION_14BIT; + break; + default: + assert(0); + } + + switch (adc_config->oversample) { + case ADC_OVERSAMPLE_DISABLED: + g_drv_instance.oversample = NRF_SAADC_OVERSAMPLE_DISABLED; + break; + case ADC_OVERSAMPLE_2X: + g_drv_instance.oversample = NRF_SAADC_OVERSAMPLE_2X; + break; + case ADC_OVERSAMPLE_4X: + g_drv_instance.oversample = NRF_SAADC_OVERSAMPLE_4X; + break; + case ADC_OVERSAMPLE_8X: + g_drv_instance.oversample = NRF_SAADC_OVERSAMPLE_8X; + break; + case ADC_OVERSAMPLE_16X: + g_drv_instance.oversample = NRF_SAADC_OVERSAMPLE_16X; + break; + case ADC_OVERSAMPLE_32X: + g_drv_instance.oversample = NRF_SAADC_OVERSAMPLE_32X; + break; + case ADC_OVERSAMPLE_64X: + g_drv_instance.oversample = NRF_SAADC_OVERSAMPLE_64X; + break; + case ADC_OVERSAMPLE_128X: + g_drv_instance.oversample = NRF_SAADC_OVERSAMPLE_128X; + break; + case ADC_OVERSAMPLE_256X: + g_drv_instance.oversample = NRF_SAADC_OVERSAMPLE_256X; + break; + default: + assert(0); + } + + g_drv_instance.calibrate = adc_config->calibrate; + } } err: if (unlock) { os_mutex_release(&dev->ad_lock); } - return (rc); -} + return rc; +} /** * Close the NRF52 ADC device. @@ -156,10 +252,22 @@ nrf52_adc_close(struct os_dev *odev) unlock = 1; } if (--(dev->ad_ref_cnt) == 0) { - nrfx_saadc_uninit(); + NVIC_DisableIRQ(SAADC_IRQn); + if (nrf_saadc_busy_check(NRF_SAADC)) { + nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STOPPED); + nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_STOP); + + while (!nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_STOPPED)); + + nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STOPPED); + nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END); + } + + nrf_saadc_disable(NRF_SAADC); + init_instance_unconf(); + clear_device_regs(); global_adc_dev = NULL; - global_adc_config = NULL; } err: @@ -181,84 +289,98 @@ err: * @return 0 on success, non-zero on failure. */ static int -nrf52_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, - void *cfgdata) +nrf52_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, void *cfgdata) { - nrf_saadc_channel_config_t *cc; + struct adc_chan_cfg *cfg = (struct adc_chan_cfg *) cfgdata; uint16_t refmv; - uint8_t res; - int rc; + nrf_saadc_resolution_t res; - cc = (nrf_saadc_channel_config_t *) cfgdata; + if (cnum > SAADC_CH_NUM) { + return OS_EINVAL; + } - rc = nrfx_saadc_channel_init(cnum, cc); - if (rc != NRFX_SUCCESS) { - goto err; + if (nrf_saadc_busy_check(NRF_SAADC)) { + return OS_EBUSY; } - 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. */ + channel_unconf(cnum); + dev->ad_chans[cnum].c_configured = 0; + if (!cfgdata) { + nrf_saadc_channel_init(NRF_SAADC, cnum, + &g_drv_instance.channels[cnum].nrf_chan); + return 0; + } + + switch (g_drv_instance.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); } - switch (cc->reference) { - case NRF_SAADC_REFERENCE_INTERNAL: - refmv = 600; /* 0.6V for NRF52 */ - break; - case NRF_SAADC_REFERENCE_VDD4: - refmv = init_adc_config->nadc_refmv / 4; - break; - default: - assert(0); + switch (cfg->reference) { + case ADC_REFERENCE_INTERNAL: + g_drv_instance.channels[cnum].nrf_chan.reference = + NRF_SAADC_REFERENCE_INTERNAL; + refmv = 600; /* 0.6V for NRF52 */ + break; + case ADC_REFERENCE_VDD_DIV_4: + g_drv_instance.channels[cnum].nrf_chan.reference = + NRF_SAADC_REFERENCE_VDD4; + refmv = init_cfg->nadc_refmv / 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; + switch (cfg->gain) { + case ADC_GAIN1_6: + refmv *= 6; + break; + case ADC_GAIN1_5: + refmv *= 5; + break; + case ADC_GAIN1_4: + refmv *= 4; + break; + case ADC_GAIN1_3: + refmv *= 3; + break; + case ADC_GAIN1_2: + refmv *= 2; + break; + case ADC_GAIN2: + refmv /= 2; + break; + case ADC_GAIN4: + refmv /= 4; + break; + default: + break; + } + + g_drv_instance.channels[cnum].pin_p = cfg->pin; + if (cfg->differential) { + g_drv_instance.channels[cnum].nrf_chan.mode = + NRF_SAADC_MODE_DIFFERENTIAL; + g_drv_instance.channels[cnum].pin_n = cfg->pin_negative; } + /* Init Channel's registers */ + nrf_saadc_channel_init(NRF_SAADC, cnum, + &g_drv_instance.channels[cnum].nrf_chan); + /* Store these values in channel definitions, for conversions to * milivolts. */ @@ -266,58 +388,56 @@ nrf52_adc_configure_channel(struct adc_dev *dev, uint8_t cnum, dev->ad_chans[cnum].c_refmv = refmv; dev->ad_chans[cnum].c_configured = 1; - return (0); -err: - return (rc); + return 0; } /** - * Set buffer to read data into. Implementation of setbuffer handler. + * 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) +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); + assert(dev); + assert(buf1); - rc = nrfx_saadc_buffer_convert((nrf_saadc_value_t *) buf1, buf_len); - if (rc != NRFX_SUCCESS) { - goto err; + if (buf_len <= 0) { + return OS_EINVAL; } + buf_len /= sizeof(nrf_saadc_value_t); + g_drv_instance.primary_buf = buf1; + g_drv_instance.primary_size = buf_len; if (buf2) { - rc = nrfx_saadc_buffer_convert((nrf_saadc_value_t *) buf2, - buf_len); - if (rc != NRFX_SUCCESS) { - goto err; - } + g_drv_instance.secondary_buf = buf2; + g_drv_instance.secondary_size = buf_len; } - return (0); -err: - return (rc); + + return 0; } static int nrf52_adc_release_buffer(struct adc_dev *dev, void *buf, int buf_len) { - int rc; + assert(dev); + assert(buf); - buf_len /= sizeof(nrf_saadc_value_t); + if (buf_len <= 0) { + return OS_EINVAL; + } - rc = nrfx_saadc_buffer_convert((nrf_saadc_value_t *) buf, buf_len); - if (rc != NRFX_SUCCESS) { - goto err; + buf_len /= sizeof(nrf_saadc_value_t); + if (!g_drv_instance.primary_buf) { + g_drv_instance.primary_buf = buf; + g_drv_instance.primary_size = buf_len; + } else if (!g_drv_instance.secondary_buf) { + g_drv_instance.secondary_buf = buf; + g_drv_instance.secondary_size = buf_len; + } else { + return OS_ENOENT; } - return (0); -err: - return (rc); + return 0; } /** @@ -326,9 +446,58 @@ err: static int nrf52_adc_sample(struct adc_dev *dev) { - nrfx_saadc_sample(); + int cnum; + int cnum_last = 0; + int used_chans = 0; + + if (nrf_saadc_busy_check(NRF_SAADC)) { + return OS_EBUSY; + } + + for (cnum = 0; cnum < SAADC_CH_NUM; cnum++) { + if (dev->ad_chans[cnum].c_configured) { + cnum_last = cnum; + used_chans++; + nrf_saadc_channel_input_set(NRF_SAADC, cnum, + g_drv_instance.channels[cnum].pin_p, + g_drv_instance.channels[cnum].pin_n); + } + } + assert(used_chans > 0); + + if (g_drv_instance.primary_size < (used_chans * sizeof(nrf_saadc_value_t))) { + return OS_ENOMEM; + } + + if ((used_chans == 1) && + (g_drv_instance.oversample != NRF_SAADC_OVERSAMPLE_DISABLED)) { + nrf_saadc_burst_set(NRF_SAADC, cnum_last, NRF_SAADC_BURST_ENABLED); + nrf_saadc_oversample_set(NRF_SAADC, g_drv_instance.oversample); + } else { + nrf_saadc_oversample_set(NRF_SAADC, NRF_SAADC_OVERSAMPLE_DISABLED); + } + + nrf_saadc_resolution_set(NRF_SAADC, g_drv_instance.resolution); + nrf_saadc_buffer_init(NRF_SAADC, g_drv_instance.primary_buf, + g_drv_instance.primary_size); + + nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END); + nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE); + nrf_saadc_int_enable(NRF_SAADC, + NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE); + + /* Start Sampling */ + nrf_saadc_enable(NRF_SAADC); - return (0); + if (g_drv_instance.calibrate) { + nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_CALIBRATEOFFSET); + } else { + nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_STOP); + nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START); + nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE); + } + + return 0; } /** @@ -337,9 +506,13 @@ nrf52_adc_sample(struct adc_dev *dev) static int nrf52_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result) { - nrf_saadc_value_t adc_value; int rc; int unlock = 0; + nrf_saadc_value_t adc_value; + + if (nrf_saadc_busy_check(NRF_SAADC)) { + return OS_EBUSY; + } if (os_started()) { rc = os_mutex_pend(&dev->ad_lock, OS_TIMEOUT_NEVER); @@ -348,11 +521,42 @@ nrf52_adc_read_channel(struct adc_dev *dev, uint8_t cnum, int *result) } unlock = 1; } - rc = nrfx_saadc_sample_convert(cnum, &adc_value); - if (rc != NRFX_SUCCESS) { + + /* Channel must be configured */ + if (!dev->ad_chans[cnum].c_configured) { + rc = OS_EINVAL; goto err; } + /* Enable the channel, set pins */ + nrf_saadc_channel_input_set(NRF_SAADC, cnum, + g_drv_instance.channels[cnum].pin_p, + g_drv_instance.channels[cnum].pin_n); + + if (g_drv_instance.oversample != NRF_SAADC_OVERSAMPLE_DISABLED) { + nrf_saadc_burst_set(NRF_SAADC, cnum, NRF_SAADC_BURST_ENABLED); + nrf_saadc_oversample_set(NRF_SAADC, g_drv_instance.oversample); + } else { + nrf_saadc_oversample_set(NRF_SAADC, NRF_SAADC_OVERSAMPLE_DISABLED); + } + + nrf_saadc_resolution_set(NRF_SAADC, g_drv_instance.resolution); + nrf_saadc_buffer_init(NRF_SAADC, &adc_value, 1); + nrf_saadc_enable(NRF_SAADC); + + nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START); + nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE); + while (!nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_END)); + + nrf_saadc_disable(NRF_SAADC); + nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STARTED); + nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END); + + /* Disable the channel, unset pins */ + nrf_saadc_channel_input_set(NRF_SAADC, cnum, + NRF_SAADC_INPUT_DISABLED, + NRF_SAADC_INPUT_DISABLED); + *result = (int) adc_value; rc = 0; @@ -360,12 +564,12 @@ err: if (unlock) { os_mutex_release(&dev->ad_lock); } - return (rc); + return rc; } static int nrf52_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off, - int *result) + int *result) { nrf_saadc_value_t val; int data_off; @@ -376,21 +580,74 @@ nrf52_adc_read_buffer(struct adc_dev *dev, void *buf, int buf_len, int off, val = *(nrf_saadc_value_t *) ((uint8_t *) buf + data_off); *result = val; - return (0); + return 0; } static int nrf52_adc_size_buffer(struct adc_dev *dev, int chans, int samples) { - return (sizeof(nrf_saadc_value_t) * chans * samples); + return sizeof(nrf_saadc_value_t) * chans * samples; +} + +void +nrf52_saadc_irq_handler(void) +{ + adc_event_type_t ev = ADC_EVENT_CALIBRATED; + void *buf = NULL; + int bufsize = 0; + + if (global_adc_dev == NULL || !global_adc_dev->ad_event_handler_func) { + ++nrf52_saadc_stats.saadc_events_failed; + return; + } + ++nrf52_saadc_stats.saadc_events; + + if (nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_END)) { + nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END); + + buf = g_drv_instance.primary_buf; + bufsize = g_drv_instance.primary_size * sizeof(nrf_saadc_value_t); + if (g_drv_instance.secondary_buf) { + g_drv_instance.primary_buf = g_drv_instance.secondary_buf; + g_drv_instance.primary_size = g_drv_instance.secondary_size; + g_drv_instance.secondary_buf = NULL; + g_drv_instance.secondary_size = 0; + + nrf_saadc_buffer_init(NRF_SAADC, + g_drv_instance.primary_buf, + g_drv_instance.primary_size); + } else { + nrf_saadc_int_disable(NRF_SAADC, NRF_SAADC_INT_ALL); + nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_STOP); + nrf_saadc_disable(NRF_SAADC); + } + + + ev = ADC_EVENT_RESULT; + global_adc_dev->ad_event_handler_func(global_adc_dev, + global_adc_dev->ad_event_handler_arg, + ev, buf, bufsize); + } else if (nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE)) { + nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE); + + global_adc_dev->ad_event_handler_func(global_adc_dev, + global_adc_dev->ad_event_handler_arg, + ev, buf, bufsize); + + nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_STOP); + nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START); + nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE); + } else { + ++nrf52_saadc_stats.saadc_events_failed; + } } #if MYNEWT_VAL(OS_SYSVIEW) static void -saadc_irq_handler(void) +sysview_irq_handler(void) { os_trace_isr_enter(); - nrfx_saadc_irq_handler(); + nrf52_saadc_irq_handler(); os_trace_isr_exit(); } #endif @@ -417,28 +674,23 @@ int nrf52_adc_dev_init(struct os_dev *odev, void *arg) { struct adc_dev *dev; - 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; + dev->ad_chan_count = SAADC_CH_NUM; - OS_DEV_SETHANDLERS(odev, nrf52_adc_open, nrf52_adc_close); - - assert(init_adc_config == NULL || init_adc_config == arg); - init_adc_config = arg; + init_cfg = (struct nrf52_adc_dev_cfg *) arg; + OS_DEV_SETHANDLERS(odev, nrf52_adc_open, nrf52_adc_close); dev->ad_funcs = &nrf52_adc_funcs; #if MYNEWT_VAL(OS_SYSVIEW) - NVIC_SetVector(SAADC_IRQn, (uint32_t) saadc_irq_handler); + NVIC_SetVector(SAADC_IRQn, (uint32_t) sysview_irq_handler); #else - NVIC_SetVector(SAADC_IRQn, (uint32_t) nrfx_saadc_irq_handler); + NVIC_SetVector(SAADC_IRQn, (uint32_t) nrf52_saadc_irq_handler); #endif - return (0); + return 0; } - - diff --git a/hw/mcu/nordic/nrf52xxx/src/nrfx_saadc_mod.c b/hw/mcu/nordic/nrf52xxx/src/nrfx_saadc_mod.c deleted file mode 100644 index 8d63e94..0000000 --- a/hw/mcu/nordic/nrf52xxx/src/nrfx_saadc_mod.c +++ /dev/null @@ -1,651 +0,0 @@ -/** - * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA - * 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. Neither the name of the copyright holder 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 "syscfg/syscfg.h" - -#if MYNEWT_VAL(BSP_NRF52) - -#include <nrfx.h> - -#if NRFX_CHECK(NRFX_SAADC_ENABLED) -#include <nrfx_saadc.h> - -#define NRFX_LOG_MODULE SAADC -#include <nrfx_log.h> - -#define EVT_TO_STR(event) \ - (event == NRF_SAADC_EVENT_STARTED ? "NRF_SAADC_EVENT_STARTED" : \ - (event == NRF_SAADC_EVENT_END ? "NRF_SAADC_EVENT_END" : \ - (event == NRF_SAADC_EVENT_DONE ? "NRF_SAADC_EVENT_DONE" : \ - (event == NRF_SAADC_EVENT_RESULTDONE ? "NRF_SAADC_EVENT_RESULTDONE" : \ - (event == NRF_SAADC_EVENT_CALIBRATEDONE ? "NRF_SAADC_EVENT_CALIBRATEDONE" : \ - (event == NRF_SAADC_EVENT_STOPPED ? "NRF_SAADC_EVENT_STOPPED" : \ - "UNKNOWN EVENT")))))) - - -typedef enum -{ - NRF_SAADC_STATE_IDLE = 0, - NRF_SAADC_STATE_BUSY = 1, - NRF_SAADC_STATE_CALIBRATION = 2 -} nrf_saadc_state_t; - - -typedef struct -{ - nrf_saadc_input_t pselp; - nrf_saadc_input_t pseln; -} nrf_saadc_psel_buffer; - -/** @brief SAADC control block.*/ -typedef struct -{ - nrfx_saadc_event_handler_t event_handler; ///< Event handler function pointer. - volatile nrf_saadc_value_t * p_buffer; ///< Sample buffer. - volatile uint16_t buffer_size; ///< Size of the sample buffer. - volatile nrf_saadc_value_t * p_secondary_buffer; ///< Secondary sample buffer. - volatile nrf_saadc_state_t adc_state; ///< State of the SAADC. - uint32_t limits_enabled_flags; ///< Enabled limits flags. - uint16_t secondary_buffer_size; ///< Size of the secondary buffer. - uint16_t buffer_size_left; ///< When low power mode is active indicates how many samples left to convert on current buffer. - nrf_saadc_psel_buffer psel[NRF_SAADC_CHANNEL_COUNT]; ///< Pin configurations of SAADC channels. - nrfx_drv_state_t state; ///< Driver initialization state. - uint8_t active_channels; ///< Number of enabled SAADC channels. - bool low_power_mode; ///< Indicates if low power mode is active. - bool conversions_end; ///< When low power mode is active indicates end of conversions on current buffer. -} nrfx_saadc_cb_t; - -static nrfx_saadc_cb_t m_cb; - -#define LOW_LIMIT_TO_FLAG(channel) ((2 * channel + 1)) -#define HIGH_LIMIT_TO_FLAG(channel) ((2 * channel)) -#define FLAG_IDX_TO_EVENT(idx) ((nrf_saadc_event_t)((uint32_t)NRF_SAADC_EVENT_CH0_LIMITH + \ - 4 * idx)) -#define LIMIT_EVENT_TO_CHANNEL(event) (uint8_t)(((uint32_t)event - \ - (uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) / 8) -#define LIMIT_EVENT_TO_LIMIT_TYPE(event)((((uint32_t)event - (uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) & 4) \ - ? NRF_SAADC_LIMIT_LOW : NRF_SAADC_LIMIT_HIGH) -#define HW_TIMEOUT 10000 - -void nrfx_saadc_irq_handler(void) -{ - if (nrf_saadc_event_check(NRF_SAADC_EVENT_END)) - { - nrf_saadc_event_clear(NRF_SAADC_EVENT_END); - NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_END)); - - if (!m_cb.low_power_mode || m_cb.conversions_end) - { - nrfx_saadc_evt_t evt; - evt.type = NRFX_SAADC_EVT_DONE; - evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.p_buffer; - evt.data.done.size = m_cb.buffer_size; - - if (m_cb.p_secondary_buffer == NULL) - { - m_cb.adc_state = NRF_SAADC_STATE_IDLE; - } - else - { - m_cb.buffer_size_left = m_cb.secondary_buffer_size; - m_cb.p_buffer = m_cb.p_secondary_buffer; - m_cb.buffer_size = m_cb.secondary_buffer_size; - m_cb.p_secondary_buffer = NULL; - if (!m_cb.low_power_mode) - { - nrf_saadc_task_trigger(NRF_SAADC_TASK_START); - } - } - m_cb.event_handler(&evt); - m_cb.conversions_end = false; - } - } - if (m_cb.low_power_mode && nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED)) - { - nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); - NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STARTED)); - - if (m_cb.buffer_size_left > m_cb.active_channels) - { - // More samples to convert than for single event. - m_cb.buffer_size_left -= m_cb.active_channels; - nrf_saadc_buffer_init((nrf_saadc_value_t *)&m_cb.p_buffer[m_cb.buffer_size - - m_cb.buffer_size_left], - m_cb.active_channels); - } - else if ((m_cb.buffer_size_left == m_cb.active_channels) && - - (m_cb.p_secondary_buffer != NULL)) - { - // Samples to convert for one event, prepare next buffer. - m_cb.conversions_end = true; - m_cb.buffer_size_left = 0; - nrf_saadc_buffer_init((nrf_saadc_value_t *)m_cb.p_secondary_buffer, - m_cb.active_channels); - } - else if (m_cb.buffer_size_left == m_cb.active_channels) - { - // Samples to convert for one event, but no second buffer. - m_cb.conversions_end = true; - m_cb.buffer_size_left = 0; - } - nrf_saadc_event_clear(NRF_SAADC_EVENT_END); - nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); - } - if (nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE)) - { - nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE); - NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_CALIBRATEDONE)); - m_cb.adc_state = NRF_SAADC_STATE_IDLE; - - nrfx_saadc_evt_t evt; - evt.type = NRFX_SAADC_EVT_CALIBRATEDONE; - m_cb.event_handler(&evt); - } - if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED)) - { - nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED); - NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STOPPED)); - m_cb.adc_state = NRF_SAADC_STATE_IDLE; - } - else - { - uint32_t limit_flags = m_cb.limits_enabled_flags; - uint32_t flag_idx; - nrf_saadc_event_t event; - - while (limit_flags) - { - flag_idx = __CLZ(limit_flags); - limit_flags &= ~((1UL << 31) >> flag_idx); - event = FLAG_IDX_TO_EVENT(flag_idx); - if (nrf_saadc_event_check(event)) - { - nrf_saadc_event_clear(event); - nrfx_saadc_evt_t evt; - evt.type = NRFX_SAADC_EVT_LIMIT; - evt.data.limit.channel = LIMIT_EVENT_TO_CHANNEL(event); - evt.data.limit.limit_type = LIMIT_EVENT_TO_LIMIT_TYPE(event); - NRFX_LOG_DEBUG("Event limit, channel: %d, limit type: %d.", - evt.data.limit.channel, - evt.data.limit.limit_type); - m_cb.event_handler(&evt); - } - } - } -} - - -nrfx_err_t nrfx_saadc_init(nrfx_saadc_config_t const * p_config, - nrfx_saadc_event_handler_t event_handler) -{ - NRFX_ASSERT(p_config); - NRFX_ASSERT(event_handler); - nrfx_err_t err_code; - - if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED) - { - err_code = NRFX_ERROR_INVALID_STATE; - NRFX_LOG_WARNING("Function: %s, error code: %s.", - __func__, - NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; - } - - m_cb.event_handler = event_handler; - nrf_saadc_resolution_set(p_config->resolution); - nrf_saadc_oversample_set(p_config->oversample); - m_cb.low_power_mode = p_config->low_power_mode; - m_cb.state = NRFX_DRV_STATE_INITIALIZED; - m_cb.adc_state = NRF_SAADC_STATE_IDLE; - m_cb.active_channels = 0; - m_cb.limits_enabled_flags = 0; - m_cb.conversions_end = false; - - nrf_saadc_int_disable(NRF_SAADC_INT_ALL); - nrf_saadc_event_clear(NRF_SAADC_EVENT_END); - nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); - NRFX_IRQ_PRIORITY_SET(SAADC_IRQn, p_config->interrupt_priority); - NRFX_IRQ_ENABLE(SAADC_IRQn); - nrf_saadc_int_enable(NRF_SAADC_INT_END); - - if (m_cb.low_power_mode) - { - nrf_saadc_int_enable(NRF_SAADC_INT_STARTED); - } - - nrf_saadc_enable(); - - err_code = NRFX_SUCCESS; - NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); - - return err_code; -} - - -void nrfx_saadc_uninit(void) -{ - NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); - - nrf_saadc_int_disable(NRF_SAADC_INT_ALL); - NRFX_IRQ_DISABLE(SAADC_IRQn); - nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP); - - // Wait for ADC being stopped. - bool result; - NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED), HW_TIMEOUT, 0, result); - NRFX_ASSERT(result); - - nrf_saadc_disable(); - m_cb.adc_state = NRF_SAADC_STATE_IDLE; - - for (uint32_t channel = 0; channel < NRF_SAADC_CHANNEL_COUNT; ++channel) - { - if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED) - { - nrfx_err_t err_code = nrfx_saadc_channel_uninit(channel); - NRFX_ASSERT(err_code == NRFX_SUCCESS); - } - } - - m_cb.state = NRFX_DRV_STATE_UNINITIALIZED; -} - - -nrfx_err_t nrfx_saadc_channel_init(uint8_t channel, - nrf_saadc_channel_config_t const * const p_config) -{ - NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); - NRFX_ASSERT(channel < NRF_SAADC_CHANNEL_COUNT); - // Oversampling can be used only with one channel. - NRFX_ASSERT((nrf_saadc_oversample_get() == NRF_SAADC_OVERSAMPLE_DISABLED) || - (m_cb.active_channels == 0)); - NRFX_ASSERT((p_config->pin_p <= NRF_SAADC_INPUT_VDD) && - (p_config->pin_p > NRF_SAADC_INPUT_DISABLED)); - NRFX_ASSERT(p_config->pin_n <= NRF_SAADC_INPUT_VDD); - - nrfx_err_t err_code; - - // A channel can only be initialized if the driver is in the idle state. - if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) - { - err_code = NRFX_ERROR_BUSY; - NRFX_LOG_WARNING("Function: %s, error code: %s.", - __func__, - NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; - } - -#ifdef NRF52_PAN_74 - if ((p_config->acq_time == NRF_SAADC_ACQTIME_3US) || - (p_config->acq_time == NRF_SAADC_ACQTIME_5US)) - { - nrf_saadc_disable(); - } -#endif //NRF52_PAN_74 - - if (m_cb.psel[channel].pselp == NRF_SAADC_INPUT_DISABLED) - { - ++m_cb.active_channels; - } - m_cb.psel[channel].pselp = p_config->pin_p; - m_cb.psel[channel].pseln = p_config->pin_n; - nrf_saadc_channel_init(channel, p_config); - nrf_saadc_channel_input_set(channel, p_config->pin_p, p_config->pin_n); - -#ifdef NRF52_PAN_74 - if ((p_config->acq_time == NRF_SAADC_ACQTIME_3US) || - (p_config->acq_time == NRF_SAADC_ACQTIME_5US)) - { - nrf_saadc_enable(); - } -#endif //NRF52_PAN_74 - - NRFX_LOG_INFO("Channel initialized: %d.", channel); - err_code = NRFX_SUCCESS; - NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; -} - - -nrfx_err_t nrfx_saadc_channel_uninit(uint8_t channel) -{ - NRFX_ASSERT(channel < NRF_SAADC_CHANNEL_COUNT); - NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); - - nrfx_err_t err_code; - - // A channel can only be uninitialized if the driver is in the idle state. - if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) - { - err_code = NRFX_ERROR_BUSY; - NRFX_LOG_WARNING("Function: %s, error code: %s.", - __func__, - NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; - } - - if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED) - { - --m_cb.active_channels; - } - m_cb.psel[channel].pselp = NRF_SAADC_INPUT_DISABLED; - m_cb.psel[channel].pseln = NRF_SAADC_INPUT_DISABLED; - nrf_saadc_channel_input_set(channel, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED); - nrfx_saadc_limits_set(channel, NRFX_SAADC_LIMITL_DISABLED, NRFX_SAADC_LIMITH_DISABLED); - NRFX_LOG_INFO("Channel denitialized: %d.", channel); - - err_code = NRFX_SUCCESS; - NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; -} - - -uint32_t nrfx_saadc_sample_task_get(void) -{ - return nrf_saadc_task_address_get( - m_cb.low_power_mode ? NRF_SAADC_TASK_START : NRF_SAADC_TASK_SAMPLE); -} - - -nrfx_err_t nrfx_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value) -{ - nrfx_err_t err_code; - - if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) - { - err_code = NRFX_ERROR_BUSY; - NRFX_LOG_WARNING("Function: %s error code: %s.", - __func__, - NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; - } - m_cb.adc_state = NRF_SAADC_STATE_BUSY; - nrf_saadc_int_disable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END); - nrf_saadc_buffer_init(p_value, 1); - if (m_cb.active_channels > 1) - { - for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i) - { - nrf_saadc_channel_input_set(i, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED); - } - } - nrf_saadc_channel_input_set(channel, m_cb.psel[channel].pselp, m_cb.psel[channel].pseln); - nrf_saadc_task_trigger(NRF_SAADC_TASK_START); - nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); - - bool result; - NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_END), HW_TIMEOUT, 0, result); - NRFX_ASSERT(result); - - nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); - nrf_saadc_event_clear(NRF_SAADC_EVENT_END); - - NRFX_LOG_INFO("Conversion value: %d, channel %d.", *p_value, channel); - - if (m_cb.active_channels > 1) - { - for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i) - { - nrf_saadc_channel_input_set(i, m_cb.psel[i].pselp, m_cb.psel[i].pseln); - } - } - - if (m_cb.low_power_mode) - { - nrf_saadc_int_enable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END); - } - else - { - nrf_saadc_int_enable(NRF_SAADC_INT_END); - } - - m_cb.adc_state = NRF_SAADC_STATE_IDLE; - - err_code = NRFX_SUCCESS; - NRFX_LOG_WARNING("Function: %s, error code: %s.", - __func__, - NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; -} - - -nrfx_err_t nrfx_saadc_buffer_convert(nrf_saadc_value_t * p_buffer, uint16_t size) -{ - NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); - NRFX_ASSERT((size % m_cb.active_channels) == 0); - nrfx_err_t err_code; - - nrf_saadc_int_disable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE); - if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION) - { - nrf_saadc_int_enable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE); - err_code = NRFX_ERROR_BUSY; - NRFX_LOG_WARNING("Function: %s, error code: %s.", - __func__, - NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; - } - if (m_cb.adc_state == NRF_SAADC_STATE_BUSY) - { - if ( m_cb.p_secondary_buffer) - { - nrf_saadc_int_enable(NRF_SAADC_INT_END); - err_code = NRFX_ERROR_BUSY; - NRFX_LOG_WARNING("Function: %s, error code: %s.", - __func__, - NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; - } - else - { - m_cb.p_secondary_buffer = p_buffer; - m_cb.secondary_buffer_size = size; - if (!m_cb.low_power_mode) - { - while (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED) == 0); - nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); - nrf_saadc_buffer_init(p_buffer, size); - } - nrf_saadc_int_enable(NRF_SAADC_INT_END); - err_code = NRFX_SUCCESS; - NRFX_LOG_WARNING("Function: %s, error code: %s.", - __func__, - NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; - } - } - nrf_saadc_int_enable(NRF_SAADC_INT_END); - m_cb.adc_state = NRF_SAADC_STATE_BUSY; - - m_cb.p_buffer = p_buffer; - m_cb.buffer_size = size; - m_cb.p_secondary_buffer = NULL; - - NRFX_LOG_INFO("Function: %s, buffer length: %d, active channels: %d.", - __func__, - size, - m_cb.active_channels); - - if (m_cb.low_power_mode) - { - m_cb.buffer_size_left = size; - nrf_saadc_buffer_init(p_buffer, m_cb.active_channels); - } - else - { - nrf_saadc_buffer_init(p_buffer, size); - nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); - nrf_saadc_task_trigger(NRF_SAADC_TASK_START); - } - - err_code = NRFX_SUCCESS; - NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; -} - - -nrfx_err_t nrfx_saadc_sample() -{ - NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); - - nrfx_err_t err_code = NRFX_SUCCESS; - if (m_cb.adc_state != NRF_SAADC_STATE_BUSY) - { - err_code = NRFX_ERROR_INVALID_STATE; - } - else if (m_cb.low_power_mode) - { - nrf_saadc_task_trigger(NRF_SAADC_TASK_START); - } - else - { - nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); - } - - NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; -} - - -nrfx_err_t nrfx_saadc_calibrate_offset() -{ - NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); - - nrfx_err_t err_code; - - if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) - { - err_code = NRFX_ERROR_BUSY; - NRFX_LOG_WARNING("Function: %s, error code: %s.", - __func__, - NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; - } - - m_cb.adc_state = NRF_SAADC_STATE_CALIBRATION; - - nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE); - nrf_saadc_int_enable(NRF_SAADC_INT_CALIBRATEDONE); - nrf_saadc_task_trigger(NRF_SAADC_TASK_CALIBRATEOFFSET); - err_code = NRFX_SUCCESS; - NRFX_LOG_INFO("Function: %s, error code: %s.", - __func__, - NRFX_LOG_ERROR_STRING_GET(err_code)); - return err_code; -} - - -bool nrfx_saadc_is_busy(void) -{ - return (m_cb.adc_state != NRF_SAADC_STATE_IDLE); -} - - -void nrfx_saadc_abort(void) -{ - if (nrfx_saadc_is_busy()) - { - nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED); - nrf_saadc_int_enable(NRF_SAADC_INT_STOPPED); - nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP); - - if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION) - { - m_cb.adc_state = NRF_SAADC_STATE_IDLE; - } - else - { - // Wait for ADC being stopped. - bool result; - NRFX_WAIT_FOR((m_cb.adc_state != NRF_SAADC_STATE_IDLE), HW_TIMEOUT, 0, result); - NRFX_ASSERT(result); - } - - nrf_saadc_int_disable(NRF_SAADC_INT_STOPPED); - - m_cb.p_buffer = 0; - m_cb.p_secondary_buffer = 0; - NRFX_LOG_INFO("Conversion aborted."); - } -} - - -void nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high) -{ - NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); - NRFX_ASSERT(m_cb.event_handler); // only non blocking mode supported - NRFX_ASSERT(limit_low >= NRFX_SAADC_LIMITL_DISABLED); - NRFX_ASSERT(limit_high <= NRFX_SAADC_LIMITH_DISABLED); - NRFX_ASSERT(limit_low < limit_high); - nrf_saadc_channel_limits_set(channel, limit_low, limit_high); - - uint32_t int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_LOW); - if (limit_low == NRFX_SAADC_LIMITL_DISABLED) - { - m_cb.limits_enabled_flags &= ~(0x80000000 >> LOW_LIMIT_TO_FLAG(channel)); - nrf_saadc_int_disable(int_mask); - } - else - { - m_cb.limits_enabled_flags |= (0x80000000 >> LOW_LIMIT_TO_FLAG(channel)); - nrf_saadc_int_enable(int_mask); - } - - int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_HIGH); - if (limit_high == NRFX_SAADC_LIMITH_DISABLED) - { - m_cb.limits_enabled_flags &= ~(0x80000000 >> HIGH_LIMIT_TO_FLAG(channel)); - nrf_saadc_int_disable(int_mask); - } - else - { - m_cb.limits_enabled_flags |= (0x80000000 >> HIGH_LIMIT_TO_FLAG(channel)); - nrf_saadc_int_enable(int_mask); - } -} - -void nrfx_enable_adc_chan(int chan, nrf_saadc_input_t pselp, - nrf_saadc_input_t pseln) -{ - NRFX_ASSERT(m_cb.active_channels < NRF_SAADC_CHANNEL_COUNT); - ++m_cb.active_channels; - nrf_saadc_channel_input_set(chan, pselp, pseln); -} - -void nrfx_disable_adc_chan(int chan) -{ - NRFX_ASSERT(m_cb.active_channels != 0); - --m_cb.active_channels; - nrf_saadc_channel_input_set(chan, NRF_SAADC_INPUT_DISABLED, - NRF_SAADC_INPUT_DISABLED); -} -#endif // NRFX_CHECK(NRFX_SAADC_ENABLED) -#endif /* MYNEWT_VAL(BSP_NRF52) */