Skip to content

Commit c97e628

Browse files
committed
[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]>
1 parent 8277731 commit c97e628

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

drivers/adc/adc_nrfx_saadc.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,21 +187,24 @@ static int input_assign(nrf_saadc_input_t *pin_p,
187187

188188
if (channel_cfg->differential) {
189189
if (channel_cfg->input_negative > ARRAY_SIZE(saadc_psels) ||
190-
channel_cfg->input_negative < NRF_SAADC_AIN0 ||
191190
(IS_ENABLED(CONFIG_NRF_PLATFORM_HALTIUM) &&
192191
(channel_cfg->input_positive > NRF_SAADC_AIN7) !=
193192
(channel_cfg->input_negative > NRF_SAADC_AIN7))) {
194193
LOG_ERR("Invalid analog negative input number: %d",
195194
channel_cfg->input_negative);
196195
return -EINVAL;
197196
}
198-
*pin_n = saadc_psels[channel_cfg->input_negative];
197+
*pin_n = channel_cfg->input_negative == NRF_SAADC_GND ?
198+
NRF_SAADC_INPUT_DISABLED :
199+
saadc_psels[channel_cfg->input_negative];
199200
} else {
200201
*pin_n = NRF_SAADC_INPUT_DISABLED;
201202
}
202203
#else
203204
*pin_p = channel_cfg->input_positive;
204-
*pin_n = channel_cfg->differential ? channel_cfg->input_negative
205+
*pin_n = channel_cfg->differential ? (channel_cfg->input_negative == NRF_SAADC_GND
206+
? NRF_SAADC_INPUT_DISABLED
207+
: channel_cfg->input_negative)
205208
: NRF_SAADC_INPUT_DISABLED;
206209
#endif
207210
LOG_DBG("ADC positive input: %d", *pin_p);
@@ -352,8 +355,14 @@ static int adc_nrfx_channel_setup(const struct device *dev,
352355
* after ADC sequence ends.
353356
*/
354357
if (channel_cfg->differential) {
355-
ch_cfg->mode = NRF_SAADC_MODE_DIFFERENTIAL;
356-
m_data.single_ended_channels &= ~BIT(channel_cfg->channel_id);
358+
if (channel_cfg->input_negative == NRF_SAADC_GND) {
359+
ch_cfg->mode = NRF_SAADC_MODE_SINGLE_ENDED;
360+
/* Do not mark as single-ended to not correct negative values. */
361+
m_data.single_ended_channels &= ~BIT(channel_cfg->channel_id);
362+
} else {
363+
ch_cfg->mode = NRF_SAADC_MODE_DIFFERENTIAL;
364+
m_data.single_ended_channels &= ~BIT(channel_cfg->channel_id);
365+
}
357366
} else {
358367
ch_cfg->mode = NRF_SAADC_MODE_SINGLE_ENDED;
359368
m_data.single_ended_channels |= BIT(channel_cfg->channel_id);

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,26 @@
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+
* zephyr,input-positive = <NRF_SAADC_AIN3>;
19+
* zephyr,input-negative = <NRF_SAADC_GND>;
20+
*
21+
* The nRF SAADC driver also supports using the nRF SAADC SE mode in
22+
* emulated "single-ended" mode, as defined by zephyr. In this mode,
23+
* negative readings will be clamped to 0 by software to emulate the
24+
* behavior of an ADC in "single-ended" mode, as defined by zephyr. To
25+
* do this, only define the positive input:
26+
*
27+
* zephyr,input-positive = <NRF_SAADC_AIN3>;
28+
*/
29+
#define NRF_SAADC_GND 0
1030
#define NRF_SAADC_AIN0 1
1131
#define NRF_SAADC_AIN1 2
1232
#define NRF_SAADC_AIN2 3

0 commit comments

Comments
 (0)