2025-08-01 4:12 AM
I am currently using a STM32MP157a on an SOC module from aries-embedded and try use the internal ADC in M4 context. However, I always get 32678 for 16bit settings regardless of the other ADC settings or channel selected. For 12 bit the value is then 2048.
I figured out that on that SOC module VDDA input of the STM32MP157 is connected to LDO2 of the STPMIC1A and there is no voltage present. I guess the LDO is not activated during boot of the Linux. I used the following settings in my dts file, for the PMIC:
&i2c4 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c4_pins_z_mx>;
pinctrl-1 = <&i2c4_sleep_pins_z_mx>;
status = "okay";
/* USER CODE BEGIN i2c4 */
/delete-property/dmas;
/delete-property/dma-names;
pmic: stpmic@33 {
compatible = "st,stpmic1";
reg = <0x33>;
interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>;
interrupt-controller;
#interrupt-cells = <2>;
status = "okay";
regulators {
compatible = "st,stpmic1-regulators";
buck1-supply = <&vin>;
buck2-supply = <&vin>;
buck3-supply = <&vin>;
buck4-supply = <&vin>;
ldo1-supply = <&v3v3>;
ldo2-supply = <&v3v3>;
ldo3-supply = <&v3v3>;
ldo5-supply = <&vin>;
ldo6-supply = <&vin>;
vref_ddr-supply = <&vin>;
boost-supply = <&vin>;
pwr_sw1-supply = <&bst_out>;
pwr_sw2-supply = <&bst_out>;
vddcore: buck1 {
regulator-name = "vddcore";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1250000>;
regulator-always-on;
regulator-initial-mode = <0>;
regulator-over-current-protection;
};
vdd_ddr: buck2 {
regulator-name = "vdd_ddr";
regulator-min-microvolt = <1250000>;
regulator-max-microvolt = <1250000>;
regulator-always-on;
regulator-initial-mode = <0>;
regulator-over-current-protection;
};
vdd: buck3 {
regulator-name = "vdd";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
st,mask-reset;
regulator-initial-mode = <0>;
regulator-over-current-protection;
};
v3v3: buck4 {
regulator-name = "v3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-over-current-protection;
regulator-initial-mode = <0>;
};
vflash: ldo1 {
regulator-name = "vflash";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
//interrupts = <IT_CURLIM_LDO1 0>;
};
vdda: ldo2 {
regulator-name = "vdda";
regulator-min-microvolt = <2900000>;
regulator-max-microvolt = <2900000>;
//interrupts = <IT_CURLIM_LDO2 0>;
regulator-always-on;
};
vdd1_lpddr: ldo3 {
regulator-name = "vdd1_lpddr";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
regulator-over-current-protection;
};
vdd_usb: ldo4 {
regulator-name = "vdd_usb";
//interrupts = <IT_CURLIM_LDO4 0>;
regulator-always-on;
};
vdd_sd: ldo5 {
regulator-name = "vdd_sd";
regulator-min-microvolt = <2900000>;
regulator-max-microvolt = <2900000>;
//interrupts = <IT_CURLIM_LDO5 0>;
regulator-boot-on;
};
v1v8: ldo6 {
regulator-name = "v1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
//interrupts = <IT_CURLIM_LDO6 0>;
};
vref_ddr: vref_ddr {
regulator-name = "vref_ddr";
regulator-always-on;
};
bst_out: boost {
regulator-name = "bst_out";
//interrupts = <IT_OCP_BOOST 0>;
};
vbus_otg: pwr_sw1 {
regulator-name = "vbus_otg";
//interrupts = <IT_OCP_OTG 0>;
};
vbus_sw: pwr_sw2 {
regulator-name = "vbus_sw";
//interrupts = <IT_OCP_SWOUT 0>;
regulator-active-discharge = <1>;
};
};
onkey {
compatible = "st,stpmic1-onkey";
//interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 0>;
//interrupt-names = "onkey-falling", "onkey-rising";
power-off-time-sec = <10>;
status = "okay";
};
watchdog {
compatible = "st,stpmic1-wdt";
status = "disabled";
};
};
/* USER CODE END i2c4 */
};
for the ADC:
&m4_adc {
pinctrl-names = "default";
pinctrl-0 = <&m4_adc_pins_mx>;
status = "okay";
/* USER CODE BEGIN m4_adc */
vref-supply = <&vrefbuf>;
/* USER CODE END m4_adc */
};
for vrefbuf:
&vrefbuf {
status = "okay";
/* USER CODE BEGIN vrefbuf */
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
vdda-supply = <&vdda>;
/* USER CODE END vrefbuf */
};
On the m4 currently I use the the following code snippets:
main(){
...
MX_ADC2_Init();
...
if(HAL_ADCEx_Calibration_Start(&hadc2, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED) != HAL_OK)
{
/* Calibration Error */
Error_Handler();
}
HAL_ADC_Start(&hadc2);
while (1)
{
if(HAL_ADC_PollForConversion(&hadc2, 100)==HAL_OK){
value = HAL_ADC_GetValue(&hadc2);
HAL_ADC_Start(&hadc2);
}else{
value = 0;
}
}
}
void MX_ADC2_Init(void)
{
/* USER CODE BEGIN ADC2_Init 0 */
/* USER CODE END ADC2_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC2_Init 1 */
/* USER CODE END ADC2_Init 1 */
/** Common config
*/
hadc2.Instance = ADC2;
hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
hadc2.Init.Resolution = ADC_RESOLUTION_16B;
hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc2.Init.LowPowerAutoWait = DISABLE;
hadc2.Init.ContinuousConvMode = DISABLE;
hadc2.Init.NbrOfConversion = 1;
hadc2.Init.DiscontinuousConvMode = DISABLE;
hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc2.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc2.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc2.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc2) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_64CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC2_Init 2 */
/* USER CODE END ADC2_Init 2 */
}
Any suggestions or help why I cannot use the internal ADC and why LDO2 is not powered on, which might be the root cause?