Skip to content

Portenta H7: ADC Implementation #76

Open
@mjs513

Description

@mjs513

In order to get ADC working on the H7 used the Giga Overlay as the model. The following changes were made to the arduino_portenta_h7_m7.overlay:


&adc1 {
	pinctrl-0 = <&adc1_inp12_pc2
    &adc1_inp13_pc3
    &adc1_inp18_pa4
    &adc1_inp3_pa6
		&adc1_inp0_pa0_c
		&adc1_inp1_pa1_c>;
	pinctrl-names = "default";
	st,adc-clock-source = <SYNC>;
	st,adc-prescaler = <4>;
	status = "okay";

	#address-cells = <1>;
	#size-cells = <0>;

	channel@c {
		reg = <12>;
		zephyr,gain = "ADC_GAIN_1";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
		zephyr,resolution = <16>;
	};
	channel@d {
		reg = <13>;
		zephyr,gain = "ADC_GAIN_1";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
		zephyr,resolution = <16>;
	};
	channel@12 {
		reg = <18>;
		zephyr,gain = "ADC_GAIN_1";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
		zephyr,resolution = <16>;
	};
	channel@3 {
		reg = <3>;
		zephyr,gain = "ADC_GAIN_1";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
		zephyr,resolution = <16>;
	};

	/* PA0_C and PA1_C */
	channel@0 {
		reg = <0>;
		zephyr,gain = "ADC_GAIN_1";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
		zephyr,resolution = <16>;
	};
	channel@1 {
		reg = <1>;
		zephyr,gain = "ADC_GAIN_1";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
		zephyr,resolution = <16>;
	};
};

&adc3 {
	pinctrl-0 = <&adc3_inp0_pc2_c
		&adc3_inp1_pc3_c>;
	pinctrl-names = "default";
	st,adc-clock-source = <SYNC>;
	st,adc-prescaler = <4>;
	status = "okay";

	#address-cells = <1>;
	#size-cells = <0>;

	channel@0 {
		reg = <0>;
		zephyr,gain = "ADC_GAIN_1";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
		zephyr,resolution = <16>;
	};
	channel@1 {
		reg = <1>;
		zephyr,gain = "ADC_GAIN_1";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
		zephyr,resolution = <16>;
	};
};
.....
		adc-pin-gpios =	<&gpioz 0 0>,			/* analog only */
					<&gpioz 1 0>,			/* analog only */
					<&gpioz 2 0>,			/* analog only */
					<&gpioz 3 0>,			/* analog only */
          <&gpioc 2 0>,
          <&gpioc 3 0>,
          <&gpioa 4 0>,
          <&gpioa 6 0>;
...
  io-channels =	<&adc1 0>,
				<&adc1 1>,
        <&adc3 0>,
        <&adc3 1>,
        <&adc1 12>,
        <&adc1 13>,
				<&adc1 18>,
				<&adc1 3>;        
	};

In the conf file enabled CONFIG_ADC=y

Also added the pure_analog_pins,h and ,cpp files modified to use the H7 Analog Pins A0-A3.

Rung out the analog pins a0-a7 using a analog joystick from adafruit:

void setup() {
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
  //pinMode(10, OUTPUT);  // PC2
  Serial.begin(115200);
  while (!Serial && millis() < 4000) {}
}

void loop() {
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  //digitalWrite(10, !digitalRead(10));
  Serial.print(analogRead(A0)); Serial.print("\t");
  Serial.print(analogRead(A1)); Serial.print("\t");
  Serial.print(analogRead(A2)); Serial.print("\t");
  Serial.print(analogRead(A3)); Serial.print("\t");
  Serial.print(analogRead(A4)); Serial.print("\t");
  Serial.print(analogRead(A5)); Serial.print("\t"); 
  Serial.print(analogRead(A6)); Serial.print("\t");
  Serial.print(analogRead(A7)); Serial.println();
  delay(250);
  if (Serial.available() ) {
    while (Serial.read() != -1) {}
    //analogRead(A4);
  }

}

While A0-A3 and A6/A7 worked as expected found A4 and A5 were non operational. We tried a few things but no luck.

@KurtE instrumented a simple test sketch to print out the pin configs

void print_gpio_regs(const char *name, GPIO_TypeDef *port) {
  //printk("GPIO%s(%p) %08X %08X %08x\n", name, port, port->MODER, port->AFR[0], port->AFR[1]);
  Serial.print("GPIO");
  Serial.print(name);
  Serial.print(" ");
  Serial.print(port->MODER, HEX);
  Serial.print(" ");
  Serial.print(port->AFR[0], HEX);
  Serial.print(" ");
  Serial.println(port->AFR[1], HEX);
}

void show_all_gpio_regs() {
  print_gpio_regs("A", (GPIO_TypeDef *)GPIOA_BASE);
  print_gpio_regs("B", (GPIO_TypeDef *)GPIOB_BASE);
  print_gpio_regs("C", (GPIO_TypeDef *)GPIOC_BASE);
  print_gpio_regs("D", (GPIO_TypeDef *)GPIOD_BASE);
  print_gpio_regs("E", (GPIO_TypeDef *)GPIOE_BASE);
  print_gpio_regs("F", (GPIO_TypeDef *)GPIOF_BASE);
  print_gpio_regs("G", (GPIO_TypeDef *)GPIOG_BASE);
  print_gpio_regs("H", (GPIO_TypeDef *)GPIOH_BASE);
  print_gpio_regs("I", (GPIO_TypeDef *)GPIOI_BASE);
  print_gpio_regs("J", (GPIO_TypeDef *)GPIOJ_BASE);
  print_gpio_regs("K", (GPIO_TypeDef *)GPIOK_BASE);
}


void setup() {
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
  //pinMode(10, OUTPUT);  // PC2
  Serial.begin(115200);
  while (!Serial && millis() < 4000) {}
  show_all_gpio_regs();
}

void loop() {
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  //digitalWrite(10, !digitalRead(10));
  Serial.print(analogRead(A0));
  Serial.print("\t");
  Serial.print(analogRead(A1));
  Serial.print("\t");
  Serial.print(analogRead(A2));
  Serial.print("\t");
  Serial.print(analogRead(A3));
  Serial.print("\t");
  Serial.print(analogRead(A4));
  Serial.print("\t");
  Serial.print(analogRead(A5));
  Serial.print("\t");
  Serial.print(analogRead(A6));
  Serial.print("\t");
  Serial.print(analogRead(A7));
  Serial.println();
  delay(250);
  if (Serial.available()) {
    show_all_gpio_regs();
    while (Serial.read() != -1) {}
    Serial.println("Paused");
    while (Serial.read() == -1) {}
    while (Serial.read() != -1) {}
    //analogRead(A4);
  }
}

and found that pins A4 and A5 modes were set to AF5 which according to the spec

Image

identifed a4 and a5 as MISO and MOSI for SPI2.

@KurtE found there was an open issue [RFC] Add device init/de-init functionality in Zephyr related to this.

So besides some PWM pins being non-operational we now have some analog pins non-operational.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions