Skip to content

Commit b056226

Browse files
jaz1-nordicjukkar
authored andcommitted
[nrf fromlist] drivers: adc: nrfx: enable negative values for single-ended ADC readings
The ADC driver API already supports ADC readings which can return signed values, these are differential readings. In Nordic's datasheet, we have a mode called "single ended", but its just a name. "Single ended" is a differential reading, with the negative channel tied to GND. This is not compatible with zephyrs definition of a single ended reading. To support Nordic's "single ended" mode, the user must configure a differential reading, with the negative input tied to ground, which the saadc driver can then use to configure the reading as Nordic SAADC "single ended", and return negative values as expected. Upstream PR #: 94069 Signed-off-by: Jakub Zymelka <[email protected]> (cherry picked from commit 84ab620)
1 parent 43727bf commit b056226

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

drivers/adc/adc_nrfx_saadc.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -191,22 +191,24 @@ static int input_assign(nrf_saadc_input_t *pin_p,
191191

192192
if (channel_cfg->differential) {
193193
if (channel_cfg->input_negative > ARRAY_SIZE(saadc_psels) ||
194-
channel_cfg->input_negative < NRF_SAADC_AIN0 ||
195194
(IS_ENABLED(CONFIG_NRF_PLATFORM_HALTIUM) &&
196195
(channel_cfg->input_positive > NRF_SAADC_AIN7) !=
197196
(channel_cfg->input_negative > NRF_SAADC_AIN7))) {
198197
LOG_ERR("Invalid analog negative input number: %d",
199198
channel_cfg->input_negative);
200199
return -EINVAL;
201200
}
202-
*pin_n = saadc_psels[channel_cfg->input_negative];
201+
*pin_n = channel_cfg->input_negative == NRF_SAADC_GND ?
202+
NRF_SAADC_INPUT_DISABLED :
203+
saadc_psels[channel_cfg->input_negative];
203204
} else {
204205
*pin_n = NRF_SAADC_INPUT_DISABLED;
205206
}
206207
#else
207208
*pin_p = channel_cfg->input_positive;
208-
*pin_n = channel_cfg->differential ? channel_cfg->input_negative
209-
: NRF_SAADC_INPUT_DISABLED;
209+
*pin_n = (channel_cfg->differential && (channel_cfg->input_negative != NRF_SAADC_GND))
210+
? channel_cfg->input_negative
211+
: NRF_SAADC_INPUT_DISABLED;
210212
#endif
211213
LOG_DBG("ADC positive input: %d", *pin_p);
212214
LOG_DBG("ADC negative input: %d", *pin_n);
@@ -356,8 +358,14 @@ static int adc_nrfx_channel_setup(const struct device *dev,
356358
* after ADC sequence ends.
357359
*/
358360
if (channel_cfg->differential) {
359-
ch_cfg->mode = NRF_SAADC_MODE_DIFFERENTIAL;
360-
m_data.single_ended_channels &= ~BIT(channel_cfg->channel_id);
361+
if (channel_cfg->input_negative == NRF_SAADC_GND) {
362+
ch_cfg->mode = NRF_SAADC_MODE_SINGLE_ENDED;
363+
/* Do not mark as single-ended to not correct negative values. */
364+
m_data.single_ended_channels &= ~BIT(channel_cfg->channel_id);
365+
} else {
366+
ch_cfg->mode = NRF_SAADC_MODE_DIFFERENTIAL;
367+
m_data.single_ended_channels &= ~BIT(channel_cfg->channel_id);
368+
}
361369
} else {
362370
ch_cfg->mode = NRF_SAADC_MODE_SINGLE_ENDED;
363371
m_data.single_ended_channels |= BIT(channel_cfg->channel_id);

include/zephyr/dt-bindings/adc/nrf-saadc.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,30 @@
77
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NRF_SAADC_H_
88
#define ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NRF_SAADC_H_
99

10+
/**
11+
* @brief Short ADC negative input to ground
12+
*
13+
* @details The nRF SAADC hardware only supports differential readings.
14+
* The nRF SAADC SE (single ended) mode is differential with the negative
15+
* input shorted to GND (ground). To use the nRF SAADC SE mode, set the
16+
* negative input to NRF_SAADC_GND:
17+
*
18+
* @code{.dts}
19+
* zephyr,input-positive = <NRF_SAADC_AIN3>;
20+
* zephyr,input-negative = <NRF_SAADC_GND>;
21+
* @endcode
22+
*
23+
* The nRF SAADC driver also supports using the nRF SAADC SE mode in
24+
* emulated "single-ended" mode, as defined by zephyr. In this mode,
25+
* negative readings will be clamped to 0 by software to emulate the
26+
* behavior of an ADC in "single-ended" mode, as defined by zephyr. To
27+
* do this, only define the positive input:
28+
*
29+
* @code{.dts}
30+
* zephyr,input-positive = <NRF_SAADC_AIN3>;
31+
* @endcode
32+
*/
33+
#define NRF_SAADC_GND 0
1034
#define NRF_SAADC_AIN0 1
1135
#define NRF_SAADC_AIN1 2
1236
#define NRF_SAADC_AIN2 3

0 commit comments

Comments
 (0)