Description
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
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.