An Analog-to-Digital Converter (ADC) is a device that translates an analog voltage to a digital value that a microprocessor can understand.
The STMicroelectronics system-on-module has two ADC controllers, each with up to 19 channels. The ADC controllers are 12-bit successive approximation analog-to-digital converters.
Available ADC pins
On the ConnectCore MP13:
-
A number of ADC channels are available at castellated pads and LGA pads, multiplexed with other functions. Check the Hardware reference manuals for information about pads and ADC channels.
On the ConnectCore MP13 Development Kit:
-
GPIOA 5 (ADC1 channel 2) is accessible on
MIKROBUS_PWM
line, connector J30
Kernel configuration
You can manage the STM32MP13 ADC drivers support through the following kernel configuration options:
-
STM32 ADC core driver (
CONFIG_STM32_ADC_CORE
) -
STM32 ADC driver (
CONFIG_STM32_ADC
)
These options are enabled as built-in on the default ConnectCore MP13 kernel configuration file.
Kernel driver
The ADC drivers are located at:
File | Description |
---|---|
STM32MP13 ADC core driver |
|
STM32MP13 ADC driver |
Device tree bindings and customization
The STM32MP13 ADC device tree binding is documented at
Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml
.
The device tree must contain entries for:
-
The ADC interface
-
The enabled channels
-
The IOMUX (for ADC channels on non-dedicated pads)
STM32MP13 ADC interface
adc_1: adc@48003000 {
compatible = "st,stm32mp13-adc-core";
reg = <0x48003000 0x400>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc ADC1>, <&rcc ADC1_K>;
clock-names = "bus", "adc";
interrupt-controller;
#interrupt-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
adc1: adc@0 {
compatible = "st,stm32mp13-adc";
#io-channel-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0>;
interrupt-parent = <&adc_1>;
interrupts = <0>;
dmas = <&dmamux1 9 0x400 0x80000001>;
dma-names = "rx";
nvmem-cells = <&vrefint>;
nvmem-cell-names = "vrefint";
status = "disabled";
channel@18 {
reg = <18>;
label = "vrefint";
};
};
};
adc_2: adc@48004000 {
reg = <0x48004000 0x400>;
compatible = "st,stm32mp13-adc-core";
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc ADC2>, <&rcc ADC2_K>;
clock-names = "bus", "adc";
interrupt-controller;
#interrupt-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
adc2: adc@0 {
compatible = "st,stm32mp13-adc";
#io-channel-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0>;
interrupt-parent = <&adc_2>;
interrupts = <0>;
dmas = <&dmamux1 10 0x400 0x80000001>;
dma-names = "rx";
nvmem-cells = <&vrefint>;
nvmem-cell-names = "vrefint";
status = "disabled";
channel@13 {
reg = <13>;
label = "vrefint";
};
channel@14 {
reg = <14>;
label = "vddcore";
};
channel@16 {
reg = <16>;
label = "vddcpu";
};
channel@17 {
reg = <17>;
label = "vddq_ddr";
};
};
};
ConnectCore MP13 Development Kit ADC interfaces and channels
-
ADC1 channel 2 is enabled on GPIO
PA5
.
&adc_1 {
/* PA5 which is shared with MikroE PWM */
pinctrl-names = "default";
pinctrl-0 = <&ccmp13_adc1_pins>;
/* External Vref (requires connecting external voltage to VREF+ pad) */
vref-supply = <&external_vref>;
/* Internal Vref (requires enabling VREFBUF in OP-TEE device tree) */
//vref-supply = <&scmi_vrefbuf>;
status = "okay";
adc1: adc@0 {
status = "okay";
channel@2 {
reg = <2>;
st,min-sample-time-nsecs = <5000>;
};
};
};
IOMUX configuration
You must configure the pads that are to be used as ADCs as ANALOG inputs.
Follow these steps to configure ADC channels on your custom design:
-
Identify the pins you want configured as ADC. Verify that they are ADC-capable and note the ADC channel they are connected to. You can find this information on the Hardware reference manuals.
-
Enable the desired channel indexes using the
st,adc-channels
property. -
Configure the IOMUX of the pins to operate as
ANALOG
. -
Compile the device tree and install it in your platform.
For example, ADC1 channel 2 is available on the ConnectCore MP13 Development Kit mikroBUS™ socket connector, which corresponds to pad PA5 of the CPU. To enable it:
&adc_1 {
/* PA5 which is shared with MikroE PWM */
pinctrl-names = "default";
pinctrl-0 = <&ccmp13_adc1_pins>;
/* External Vref (requires connecting external voltage to VREF+ pad) */
// vref-supply = <&external_vref>;
/* Internal Vref (requires enabling VREFBUF in OP-TEE device tree) */
vref-supply = <&scmi_vrefbuf>;
status = "okay";
adc1: adc@0 {
status = "okay";
channel@2 {
reg = <2>;
st,min-sample-time-nsecs = <5000>;
};
};
};
&pinctrl {
ccmp13_adc1_pins: ccmp13_adc1-pins-0 {
pins {
pinmux = <STM32_PINMUX('A', 5, ANALOG)>; /* ADC1 in2 */
};
};
};
Voltage reference
The ADC block supports the following voltage references:
-
Internal VREFBUF regulator
-
External voltage reference supplied through
VREF+
pad.
Internal voltage reference (VREFBUF regulator)
VREFBUF is a STM32MP13 internal voltage regulator supplied via the scmi_vdd_adc
regulator of the PMIC.
You can configure VREFBUF to supply one of the following voltages to output at the VREF+
pin:
-
2.5 V
-
2.048 V
-
1.8 V
-
1.65 V
On the ConnectCore MP13, the ADC voltage reference is configured to use an external voltage reference, and the internal VREFBUF is disabled.
To configure the ADC to use the VREFBUF regulator as voltage reference, make the following change to your Linux device tree:
diff --git a/arch/arm/boot/dts/ccmp133-dvk.dts b/arch/arm/boot/dts/ccmp133-dvk.dts
index 3ae234f75eab..a8f8cafca77b 100644
--- a/arch/arm/boot/dts/ccmp133-dvk.dts
+++ b/arch/arm/boot/dts/ccmp133-dvk.dts
@@ -138,10 +138,10 @@ &adc_1 {
pinctrl-names = "default";
pinctrl-0 = <&ccmp13_adc1_pins>;
/* External Vref (requires connecting external voltage to VREF+ pad) */
- vref-supply = <&external_vref>;
+ // vref-supply = <&external_vref>;
/* Internal Vref (this outputs VREFBUF voltage at VREF+ pad) */
- //vref-supply = <&scmi_vrefbuf>;
+ vref-supply = <&scmi_vrefbuf>;
status = "okay";
adc1: adc@0 {
Optionally, you can configure the regulator to your desired voltage (2.5 V by default):
/*
* VREFBUF can be set to 2.5 V, 2.048 V, 1.8 V or 1.65 V which are
* output at VREF+ pad.
*/
&scmi_vrefbuf {
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
};
If you plan to measure signals of less voltage, you can get more accurate results by changing the regulator-min-microvolt and regulator-max-microvolt properties to any of the other voltages.
|
External voltage reference
You can use an external voltage reference for the ADC. This external voltage reference must be between the limits:
-
Min: 1.62 V
-
Max: 3.3 V
To use an external voltage reference:
-
Add a fixed regulator node for the external regulator, with its voltage: For example:
/ { regulators { /* * External regulator for ADC. * This regulator DOES NOT exist on the DVK. It is only * a helper for testing the ADC channels. * To make use of it, you need to supply externally the * configured voltage to the VREF+ pad. * * NOTE: This is incompatible with using the internal VREFBUF * regulator, which outputs a voltage at VREF+ pad. */ external_vref: regulator@99 { reg = <99>; compatible = "regulator-fixed"; regulator-name = "external-vref"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; }; };
-
Set the property
vref-supply
of the ADC node to use the external regulator:&adc_1 { vref-supply = <&external_vref>; };
-
If enabled, disable the internal
vrefbuf
regulator. See Internal voltage reference (VREFBUF regulator). -
Supply the voltage configured on the device tree at
VREF+
pad. -
Enable the VDDA regulator to remain on all the time. This prevents the analog block drain voltage out of your external voltage reference when the system goes to suspend.
&scmi_vdd_adc { regulator-always-on; };
Formula
The value read on the ADC inputs responds to the formula:
\$V = (V_(RAW) + V_(OFFSET)) * V_(SCALE)\$
where:
-
VRAW is the input voltage converted by the ADC.
-
VOFFSET is the ADC voltage offset.
-
VSCALE is the ADC voltage scale value. This is automatically calculated basing on the Voltage reference on your device tree.
Using the ADCs
The ADC drivers are designed as standard Industrial I/O (IIO) device drivers that can be accessed from the sysfs or from user applications.
Sysfs access
When enabled, the ADC drivers create the corresponding device entries in the IIO sysfs directory (/sys/bus/iio/devices
).
To determine which entry corresponds to which driver, read the name
descriptors with:
# grep "" /sys/bus/iio/devices/iio\:device*/name
/sys/bus/iio/devices/iio:device0/name:48003000.adc:adc@0
In this example, device0
corresponds to ADC1.
The driver creates:
-
A file entry
in_voltage_offset
with the voltage offset. -
A file entry
in_voltage_scale
with the voltage scale. -
A file entry
in_voltageX_raw
for each ADC channel, where X corresponds to the channel number.
Read the input value of a channel with:
# cat /sys/bus/iio/devices/iio\:device0/in_voltage2_raw
4030
# cat /sys/bus/iio/devices/iio\:device0/in_voltage_offset
0
# cat /sys/bus/iio/devices/iio\:device0/in_voltage_scale
0.805664062
The returned value in in_voltage2_raw
is a decimal number with the result of the conversion.
In the example, and according to the Formula:
Sample application
An example application called apix-adc-example
is included in the dey-examples-digiapix recipe (part of dey-examples package) of the meta-digi layer.
This application shows how to access the ADCs using Digi APIx library on the ConnectCore MP13 platform.
Go to GitHub to see the application instructions and source code.
See ADC API for more information about the ADC APIx.