Skip to content

Commit c2f829b

Browse files
committed
Portenta H7M7 support for analogWrite/analogRead
@mjs513 and I added/modified the device tree for this board, with the tables to support PWM (analogWrite) and analogRead on some of the Analog pins. Note: there are some issues with A4/A5 in that those pins are also on the same pins that support SPI. And when SPI is enabled, the GPIOC pin configuration is setup by the device tree to be MODER to be set for Alternat function and their AF set to 5. The analogRead code does not does not update these tables and as such analogRead fails. We found that if y ou disable SPI then they work better. I currently left the SPI enabled. Probably need to add something that when analogRead is called that it updates the GPIO registers to make it work. I am ecurrently experimenting with a hack in my test sketch that appears to change the MODER of those pins back to 3, but so far that does not appear to be sufficent: ``` static const struct gpio_dt_spec arduino_pins[] = {DT_FOREACH_PROP_ELEM_SEP( DT_PATH(zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))}; void pinModeAnalog(pin_size_t pinNumber) { gpio_pin_configure_dt(&arduino_pins[pinNumber], GPIO_INPUT /*| GPIO_ACTIVE_HIGH */ | GPIO_MODE_ANALOG); } ``` On the analogWrites, this code has optionally in place that allows duplicate pins in the device tree GPIO list, by changing how I read in the PWM table from the Tree, instead of summing all of the matches in the GPIO tree, it instead saves the GPIO Port and pin number and uses them for the compare. Again this depends on if we wish for the Pin numbers for the functions like digitalRead/digitalWrite to match those used by the MBED version. I still have the last 3 truncated K5-K7 which are used by the LEDs and fault but depending on directions, can find other solutions. enable spi2
1 parent 7da8a97 commit c2f829b

File tree

6 files changed

+300
-16
lines changed

6 files changed

+300
-16
lines changed

Diff for: cores/arduino/zephyrCommon.cpp

+29-5
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,29 @@ const struct pwm_dt_spec arduino_pwm[] =
140140
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwms, PWM_DT_SPEC) };
141141

142142
/* pwm-pins node provides a mapping digital pin numbers to pwm channels */
143+
#if 1
144+
static const struct gpio_dt_spec arduino_pwm_pins[] = {DT_FOREACH_PROP_ELEM_SEP(
145+
DT_PATH(zephyr_user), pwm_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))};
146+
147+
size_t pwm_pin_index(pin_size_t pinNumber) {
148+
printk("pwm_pin_index: %u: ", pinNumber);
149+
if (pinNumber >= ARRAY_SIZE(arduino_pins)) {
150+
return (size_t)-1;
151+
}
152+
printk("(%p %u):", arduino_pins[pinNumber].port, arduino_pins[pinNumber].pin);
153+
for(size_t i=0; i<ARRAY_SIZE(arduino_pwm_pins); i++) {
154+
printk(" [%p,%u]", arduino_pwm_pins[i].port, arduino_pwm_pins[i].pin);
155+
if ((arduino_pwm_pins[i].port == arduino_pins[pinNumber].port) && (arduino_pwm_pins[i].pin == arduino_pins[pinNumber].pin)) {
156+
printk("\n");
157+
return i;
158+
}
159+
}
160+
printk("\n");
161+
return (size_t)-1;
162+
}
163+
164+
165+
#else
143166
const pin_size_t arduino_pwm_pins[] =
144167
{ DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwm_pin_gpios, PWM_PINS) };
145168
@@ -151,7 +174,7 @@ size_t pwm_pin_index(pin_size_t pinNumber) {
151174
}
152175
return (size_t)-1;
153176
}
154-
177+
#endif
155178
#endif //CONFIG_PWM
156179

157180
#ifdef CONFIG_ADC
@@ -293,12 +316,13 @@ void delay(unsigned long ms) { k_sleep(K_MSEC(ms)); }
293316
void delayMicroseconds(unsigned int us) { k_sleep(K_USEC(us)); }
294317

295318
unsigned long micros(void) {
319+
296320
#ifdef CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER
297-
return k_cyc_to_us_floor32(k_cycle_get_64());
321+
return k_cyc_to_us_floor32(k_cycle_get_64());
298322
#else
299-
return k_cyc_to_us_floor32(k_cycle_get_32());
300-
#endif
301-
}
323+
return k_cyc_to_us_floor32(k_cycle_get_32());
324+
#endif
325+
}
302326

303327
unsigned long millis(void) { return k_uptime_get_32(); }
304328

Diff for: loader/boards/arduino_portenta_h7_m7.conf

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ CONFIG_SHELL_STACK_SIZE=32768
2424
CONFIG_MAIN_STACK_SIZE=32768
2525
CONFIG_LLEXT_HEAP_SIZE=128
2626

27-
#CONFIG_ADC=y
28-
#CONFIG_PWM=y
27+
CONFIG_ADC=y
28+
CONFIG_PWM=y
2929
CONFIG_DMA=y
3030
CONFIG_MEMC=y
3131
CONFIG_SPI_ASYNC=y

Diff for: loader/boards/arduino_portenta_h7_m7.overlay

+194-9
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,163 @@
4040
pinctrl-names = "default";
4141
};
4242

43-
&dmamux1 {
43+
&timers1 {
4444
status = "okay";
45+
st,prescaler = <0>;
46+
47+
pwm1: pwm {
48+
status = "okay";
49+
pinctrl-0 = <&tim1_ch1_pk1 &tim1_ch2_pj11>;
50+
pinctrl-names = "default";
51+
};
4552
};
4653

47-
&dma1 {
54+
&timers3 {
55+
status = "okay";
56+
st,prescaler = <100>;
57+
58+
pwm3: pwm {
59+
status = "okay";
60+
pinctrl-0 = <&tim3_ch1_pc6 &tim3_ch2_pc7>;
61+
pinctrl-names = "default";
62+
};
63+
};
64+
65+
&timers8 {
66+
status = "okay";
67+
st,prescaler = <100>;
68+
69+
pwm8: pwm {
70+
status = "okay";
71+
pinctrl-0 = <&tim8_ch3n_ph15 &tim8_ch2_pj10 &tim8_ch2n_pj7>;
72+
pinctrl-names = "default";
73+
};
74+
};
75+
76+
&timers12 {
4877
status = "okay";
78+
st,prescaler = <100>;
79+
80+
pwm12: pwm {
81+
status = "okay";
82+
pinctrl-0 = <&tim12_ch1_ph6>;
83+
pinctrl-names = "default";
84+
};
85+
};
86+
87+
&pwm1 {
88+
/* Use the pwmclock node to start the clock generation */
89+
pwmclock: pwmclock {
90+
status = "okay";
91+
compatible = "pwm-clock";
92+
clock-frequency = <0>;
93+
#clock-cells = <1>;
94+
pwms = <&pwm1 2 PWM_HZ(12000000) PWM_POLARITY_NORMAL>;
95+
};
4996
};
5097

5198
&rng {
5299
status = "okay";
53100
};
54101

102+
&dmamux1 {
103+
status = "okay";
104+
};
105+
106+
&dma1 {
107+
status = "okay";
108+
};
109+
110+
111+
&adc1 {
112+
pinctrl-0 = <&adc1_inp12_pc2
113+
&adc1_inp13_pc3
114+
&adc1_inp18_pa4
115+
&adc1_inp3_pa6
116+
&adc1_inp0_pa0_c
117+
&adc1_inp1_pa1_c>;
118+
pinctrl-names = "default";
119+
st,adc-clock-source = <SYNC>;
120+
st,adc-prescaler = <4>;
121+
status = "okay";
122+
123+
#address-cells = <1>;
124+
#size-cells = <0>;
125+
126+
channel@c {
127+
reg = <12>;
128+
zephyr,gain = "ADC_GAIN_1";
129+
zephyr,reference = "ADC_REF_INTERNAL";
130+
zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
131+
zephyr,resolution = <16>;
132+
};
133+
channel@d {
134+
reg = <13>;
135+
zephyr,gain = "ADC_GAIN_1";
136+
zephyr,reference = "ADC_REF_INTERNAL";
137+
zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
138+
zephyr,resolution = <16>;
139+
};
140+
channel@12 {
141+
reg = <18>;
142+
zephyr,gain = "ADC_GAIN_1";
143+
zephyr,reference = "ADC_REF_INTERNAL";
144+
zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
145+
zephyr,resolution = <16>;
146+
};
147+
channel@3 {
148+
reg = <3>;
149+
zephyr,gain = "ADC_GAIN_1";
150+
zephyr,reference = "ADC_REF_INTERNAL";
151+
zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
152+
zephyr,resolution = <16>;
153+
};
154+
155+
/* PA0_C and PA1_C */
156+
channel@0 {
157+
reg = <0>;
158+
zephyr,gain = "ADC_GAIN_1";
159+
zephyr,reference = "ADC_REF_INTERNAL";
160+
zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
161+
zephyr,resolution = <16>;
162+
};
163+
channel@1 {
164+
reg = <1>;
165+
zephyr,gain = "ADC_GAIN_1";
166+
zephyr,reference = "ADC_REF_INTERNAL";
167+
zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
168+
zephyr,resolution = <16>;
169+
};
170+
};
171+
172+
&adc3 {
173+
pinctrl-0 = <&adc3_inp0_pc2_c
174+
&adc3_inp1_pc3_c>;
175+
pinctrl-names = "default";
176+
st,adc-clock-source = <SYNC>;
177+
st,adc-prescaler = <4>;
178+
status = "okay";
179+
180+
#address-cells = <1>;
181+
#size-cells = <0>;
182+
183+
channel@0 {
184+
reg = <0>;
185+
zephyr,gain = "ADC_GAIN_1";
186+
zephyr,reference = "ADC_REF_INTERNAL";
187+
zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
188+
zephyr,resolution = <16>;
189+
};
190+
channel@1 {
191+
reg = <1>;
192+
zephyr,gain = "ADC_GAIN_1";
193+
zephyr,reference = "ADC_REF_INTERNAL";
194+
zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
195+
zephyr,resolution = <16>;
196+
};
197+
};
198+
199+
55200
/ {
56201
chosen {
57202
zephyr,console = &usart6;
@@ -293,20 +438,60 @@
293438
<&gpiok 1 0>,
294439
<&gpiok 2 0>,
295440
<&gpiok 3 0>,
296-
<&gpiok 4 0>,
297-
<&gpiok 5 0>,
298-
<&gpiok 6 0>,
299-
<&gpiok 7 0>;
441+
<&gpiok 4 0>;
442+
443+
/* commented out for now to allow LEDs to work
444+
/* <&gpiok 5 0>, */
445+
/* <&gpiok 6 0>, */
446+
/* <&gpiok 7 0>; */
300447

301448

302449

303450
builtin-led-gpios = <&gpiok 5 GPIO_ACTIVE_LOW>,
304-
<&gpiok 6 GPIO_ACTIVE_LOW>,
305-
<&gpiok 7 GPIO_ACTIVE_LOW>;
306-
451+
<&gpiok 6 GPIO_ACTIVE_LOW>,
452+
<&gpiok 7 GPIO_ACTIVE_LOW>;
453+
454+
pwm-pin-gpios = //<&gpioa 8 0>,
455+
<&gpioc 6 0>,
456+
<&gpioc 7 0>,
457+
//<&gpiog 7 0>,
458+
<&gpioj 11 0>,
459+
<&gpiok 1 0>,
460+
<&gpioh 15 0>,
461+
<&gpioj 7 0>,
462+
<&gpioj 10 0>,
463+
<&gpioh 6 0>;
464+
465+
adc-pin-gpios = <&gpioz 0 0>, /* analog only */
466+
<&gpioz 1 0>, /* analog only */
467+
<&gpioz 2 0>, /* analog only */
468+
<&gpioz 3 0>, /* analog only */
469+
<&gpioc 2 0>,
470+
<&gpioc 3 0>,
471+
<&gpioa 4 0>,
472+
<&gpioa 6 0>;
473+
307474
serials = <&cdc_acm_uart0>,<&usart6>, <&usart1>, <&uart4>;
308475
cdc-acm = <&cdc_acm_uart0>;
309476
i2cs = <&i2c3>, <&i2c1>, <&i2c4>;
310477
spis = <&spi2>;
478+
pwms = //<&pwm8 1 PWM_HZ(500) PWM_POLARITY_NORMAL>,
479+
<&pwm3 1 PWM_HZ(500) PWM_POLARITY_NORMAL>,
480+
<&pwm3 2 PWM_HZ(500) PWM_POLARITY_NORMAL>,
481+
<&pwm1 2 PWM_HZ(12000000) PWM_POLARITY_NORMAL>,
482+
<&pwm1 1 PWM_HZ(5000) PWM_POLARITY_NORMAL>,
483+
<&pwm8 1 PWM_HZ(500) PWM_POLARITY_INVERTED>,
484+
<&pwm8 3 PWM_HZ(500) PWM_POLARITY_INVERTED>,
485+
<&pwm8 2 PWM_HZ(500) PWM_POLARITY_NORMAL>,
486+
<&pwm12 1 PWM_HZ(500) PWM_POLARITY_NORMAL>;
487+
488+
io-channels = <&adc1 0>,
489+
<&adc1 1>,
490+
<&adc3 0>,
491+
<&adc3 1>,
492+
<&adc1 12>,
493+
<&adc1 13>,
494+
<&adc1 18>,
495+
<&adc1 3>;
311496
};
312497
};

Diff for: variants/arduino_portenta_h7/pure_analog_pins.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include "pure_analog_pins.h"
2+
3+
#undef A0
4+
#undef A1
5+
#undef A2
6+
#undef A3
7+
8+
PureAnalogPin A0_PURE(0);
9+
PureAnalogPin A1_PURE(1);
10+
PureAnalogPin A2_PURE(2);
11+
PureAnalogPin A3_PURE(3);
12+
13+
int getAnalogReadResolution();
14+
15+
int analogRead(PureAnalogPin pin) {
16+
return ::analogRead(A0 + pin.get());
17+
}

Diff for: variants/arduino_portenta_h7/pure_analog_pins.h

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#ifndef _PURE_ANALOG_PINS_
2+
#define _PURE_ANALOG_PINS_
3+
4+
/******************************************************************************
5+
* INCLUDE
6+
******************************************************************************/
7+
8+
#include "Arduino.h"
9+
10+
/******************************************************************************
11+
* PREPROCESSOR-MAGIC
12+
******************************************************************************/
13+
14+
#define PURE_ANALOG_AS_DIGITAL_ATTRIBUTE __attribute__ ((error("Can't use pins A0-A3 as digital")))
15+
16+
/******************************************************************************
17+
* TYPEDEF
18+
******************************************************************************/
19+
20+
class PureAnalogPin {
21+
public:
22+
PureAnalogPin(int _pin) : pin(_pin) {};
23+
int get() {
24+
return pin;
25+
};
26+
bool operator== (PureAnalogPin const & other) const {
27+
return pin == other.pin;
28+
}
29+
//operator int() = delete;
30+
__attribute__ ((error("Change me to a #define"))) operator int();
31+
private:
32+
int pin;
33+
};
34+
35+
extern PureAnalogPin A0_PURE;
36+
extern PureAnalogPin A1_PURE;
37+
extern PureAnalogPin A2_PURE;
38+
extern PureAnalogPin A3_PURE;
39+
40+
#define A0 A0_PURE
41+
#define A1 A1_PURE
42+
#define A2 A2_PURE
43+
#define A3 A3_PURE
44+
45+
/******************************************************************************
46+
* FUNCTION DECLARATION
47+
******************************************************************************/
48+
49+
void PURE_ANALOG_AS_DIGITAL_ATTRIBUTE pinMode (PureAnalogPin pin, PinMode mode);
50+
PinStatus PURE_ANALOG_AS_DIGITAL_ATTRIBUTE digitalRead (PureAnalogPin pin);
51+
void PURE_ANALOG_AS_DIGITAL_ATTRIBUTE digitalWrite(PureAnalogPin pin, PinStatus value);
52+
int analogRead (PureAnalogPin pin);
53+
void PURE_ANALOG_AS_DIGITAL_ATTRIBUTE analogWrite (PureAnalogPin pin, int value);
54+
55+
#undef PURE_ANALOG_AS_DIGITAL_ATTRIBUTE
56+
57+
#endif /* _PURE_ANALOG_PINS_ */

Diff for: variants/arduino_portenta_h7/variant.h

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
6+
#include "pure_analog_pins.h"
67

78
// TODO: correctly handle these legacy defines
89
#define MOSI 0

0 commit comments

Comments
 (0)