arduino / ArduinoCore-mbed

347 stars 202 forks source link

Strange Arduino Mbed OS RP2040 for Raspberry Pi Pico analogWrite() / PWM Behavior #613

Open dlkeng opened 1 year ago

dlkeng commented 1 year ago

Arduino Mbed OS RP2040 for Raspberry Pi Pico - Version 3.5.4

In exploring the use of analogWrite() and digitalWrite() on the Raspberry Pi Pico using Arduino, I have discovered some strange behaviors when switching between those modes on the same GPIO pin.

Operational Issues:


Issue 1:

Issue 2:

Issue 3:

It was expected that the analogWrite() and digitalWrite() functions would always automatically take care of ensuring the correct function mode was set for the associated GPIO pin. Instead, it appears that this only the case on the first instance of using those functions for a GPIO pin.

--------------------------------------------------------------------------------------------
Detailed tracing of the above described issues follows below. This includes showing the
function state of the specified GPIO pin before and after each operation to configure
the pin. Also, a dump of the associated PWM registers is also shown after a PWM
configuration operation. "<---------" items note commentary items of interest.
Work-arounds are also shown to restore a GPIO pin to its expected operation.
--------------------------------------------------------------------------------------------
Raspberry Pi Pico Arduino PWM Output Testing
Available commands
------------------
pwm [<pin> [<duty> | off | on | stat]]  : Output PWM on specified I/O pin
gpio [<pin> [<0 | 1> | out | in | off]] : Output to specified I/O pin
--------------------------------------------------------------------------------------------

Issue #1:
=========
RESET -> PWM2 -> PWM3 -> PWM2
-----------------------------
-> pwm 2 64
pinFunc: GPIO_FUNC_NULL
{analogWrite(2, 64)}
PWM: GP2, Duty 64
pinFunc: GPIO_FUNC_PWM      <--------- OK, has PWM 25% output

-> pwm 2 stat
pinFunc: GPIO_FUNC_PWM
Slice: 1
CSR: 0x1 - DIVMODE:FREE_RUNNING, Enabled
DIV: 0xFA0 - INT:250, FRAC:0
CTR: 0x3A0 (928)
CC:  0xFB - B:0, A:251      <--------- OK, CHB off, CHA 25%
TOP: 0x3E8 (1000)
EN:  0x2 - CH2

-> pwm 3 128
pinFunc: GPIO_FUNC_NULL
{analogWrite(3, 128)}
PWM: GP3, Duty 128
pinFunc: GPIO_FUNC_PWM      <--------- OK, has PWM 50% output, but output 2 goes low

-> pwm 3 stat
pinFunc: GPIO_FUNC_PWM
Slice: 1
CSR: 0x1 - DIVMODE:FREE_RUNNING, Enabled
DIV: 0xFA0 - INT:250, FRAC:0
CTR: 0x391 (913)
CC:  0x1F60000 - B:502, A:0 <--------- OK, CHB 50%, Bad, CHA off (CHA should not have been modified!)
TOP: 0x3E8 (1000)
EN:  0x2 - CH2

-> pwm 2 192
pinFunc: GPIO_FUNC_PWM
{analogWrite(2, 192)}
PWM: GP2, Duty 192
pinFunc: GPIO_FUNC_PWM      <--------- OK, has PWM 75% output

-> pwm 2 stat
pinFunc: GPIO_FUNC_PWM
Slice: 1
CSR: 0x1 - DIVMODE:FREE_RUNNING, Enabled
DIV: 0xFA0 - INT:250, FRAC:0
CTR: 0x125 (293)
CC:  0x1F602F1 - B:502, A:753   <--------- OK, CHB 50%, CHA 75%
TOP: 0x3E8 (1000)
EN:  0x2 - CH2

--------------------------------------------------------------------------------------------

Issue #2:
=========
RESET -> PWM -> GPIO -> PWM fails
---------------------------------
-> pwm 2 64
pinFunc: GPIO_FUNC_NULL
{analogWrite(2, 64)}
PWM: GP2, Duty 64
pinFunc: GPIO_FUNC_PWM      <--------- OK, has PWM 25% output

-> pwm 2 stat
pinFunc: GPIO_FUNC_PWM
Slice: 1
CSR: 0x1 - DIVMODE:FREE_RUNNING, Enabled
DIV: 0xFA0 - INT:250, FRAC:0
CTR: 0x1B5 (437)
CC:  0xFB - B:0, A:251
TOP: 0x3E8 (1000)
EN:  0x2 - CH2

-> gpio 2 1
pinFunc: GPIO_FUNC_PWM
{digitalWrite(2, 1)}
GPIO: GP2, 1
pinFunc: GPIO_FUNC_SIO      <--------- OK, output high

-> pwm 2 128
pinFunc: GPIO_FUNC_SIO
{analogWrite(2, 128)}
PWM: GP2, Duty 128
pinFunc: GPIO_FUNC_SIO      <--------- FAILED, no PWM output, should be GPIO_FUNC_PWM

-> pwm 2 stat
pinFunc: GPIO_FUNC_SIO
Slice: 1
CSR: 0x1 - DIVMODE:FREE_RUNNING, Enabled
DIV: 0xFA0 - INT:250, FRAC:0
CTR: 0x122 (290)
CC:  0x1F6 - B:0, A:502
TOP: 0x3E8 (1000)
EN:  0x2 - CH2

-> pwm 2 on
pinFunc: GPIO_FUNC_SIO
{gpio_set_function(2, GPIO_FUNC_PWM)}
PWM: GP2, Duty On
pinFunc: GPIO_FUNC_PWM      <--------- OK, now has PWM 50% output

-> pwm 2 32
pinFunc: GPIO_FUNC_PWM
{analogWrite(2, 32)}
PWM: GP2, Duty 32
pinFunc: GPIO_FUNC_PWM      <--------- OK, has PWM 12% output

-> pwm 2 stat
pinFunc: GPIO_FUNC_PWM
Slice: 1
CSR: 0x1 - DIVMODE:FREE_RUNNING, Enabled
DIV: 0xFA0 - INT:250, FRAC:0
CTR: 0x1F7 (503)
CC:  0x7D - B:0, A:125
TOP: 0x3E8 (1000)
EN:  0x2 - CH2

-> gpio 2 0
pinFunc: GPIO_FUNC_PWM
{digitalWrite(2, 0)}
GPIO: GP2, 0
pinFunc: GPIO_FUNC_PWM      <--------- FAILED, still PWM output, should be GPIO_FUNC_SIO

--------------------------------------------------------------------------------------------

Issue #3:
=========
RESET -> GPIO -> PWM -> GPIO fails
----------------------------------
-> gpio 2 1
pinFunc: GPIO_FUNC_NULL
{digitalWrite(2, 1)}
GPIO: GP2, 1
pinFunc: GPIO_FUNC_SIO      <--------- OK, output high

-> pwm 2 64
pinFunc: GPIO_FUNC_SIO
{analogWrite(2, 64)}
PWM: GP2, Duty 64
pinFunc: GPIO_FUNC_PWM      <--------- OK, has PWM 25% output

-> pwm 2 stat
pinFunc: GPIO_FUNC_PWM
Slice: 1
CSR: 0x1 - DIVMODE:FREE_RUNNING, Enabled
DIV: 0xFA0 - INT:250, FRAC:0
CTR: 0x253 (595)
CC:  0xFB - B:0, A:251
TOP: 0x3E8 (1000)
EN:  0x2 - CH2

-> gpio 2 1
pinFunc: GPIO_FUNC_PWM
{digitalWrite(2, 1)}
GPIO: GP2, 1
pinFunc: GPIO_FUNC_PWM      <--------- FAILED, still PWM output, should be GPIO_FUNC_SIO

-> gpio 2 out
pinFunc: GPIO_FUNC_PWM
{pinMode(2, OUTPUT)}
GPIO: GP2, Out
pinFunc: GPIO_FUNC_SIO      <--------- OK, output low

-> gpio 2 1
pinFunc: GPIO_FUNC_SIO
{digitalWrite(2, 1)}
GPIO: GP2, 1
pinFunc: GPIO_FUNC_SIO      <--------- OK, output high

-> pwm 2 32
pinFunc: GPIO_FUNC_SIO
{analogWrite(2, 32)}
PWM: GP2, Duty 32
pinFunc: GPIO_FUNC_SIO      <--------- FAILED, no PWM output, should be GPIO_FUNC_PWM

-> pwm 2 stat
pinFunc: GPIO_FUNC_SIO
Slice: 1
CSR: 0x1 - DIVMODE:FREE_RUNNING, Enabled
DIV: 0xFA0 - INT:250, FRAC:0
CTR: 0x3D (61)
CC:  0x7D - B:0, A:125
TOP: 0x3E8 (1000)
EN:  0x2 - CH2

--------------------------------------------------------------------------------------------
aentinger commented 1 year ago

Hi @dlkeng :coffee: :wave:

It looks like you've got some test program already. Could you please share it?

Cheers, Alex

dlkeng commented 1 year ago

Hi Alex,

The PWM_Test Arduino sketch can be downloaded from my Dropbox at the following link: https://www.dropbox.com/s/drrnjofrbacpwjl/PWM_Test.zip?dl=1

This program is command-line driven from the Pico's USB COM port. Enter "help" to show a list of available commands.

Dan

aentinger commented 1 year ago

What are you compiling this sketch with? I've got the same 3.5.4 version that you claim to have:

arduino-cli core list | grep mbed_nano
arduino:mbed_nano     3.5.4     3.5.4  Arduino Mbed OS Nano Boards

Compiling via

arduino-cli compile -b arduino:mbed_nano:nanorp2040connect -v PWM_Test

ends with

/home/alex/projects/arduino/PWM_Test/PWM_Test.ino:35:2: error: #error "Missing Raspberry Pi Pico board definition!"
 #error "Missing Raspberry Pi Pico board definition!"
  ^~~~~

Used platform     Version Path                                                           
arduino:mbed_nano 3.5.4   /home/alex/.arduino15/packages/arduino/hardware/mbed_nano/3.5.4

This is because you are using the wrong #ifdefs, should be this instead:

-#ifdef ARDUINO_ARCH_MBED_RP2040
+#if defined(ARDUINO_ARCH_MBED_NANO) && defined(ARDUINO_NANO_RP2040_CONNECT)

Compiling for Raspberry Pi Pico fails with different errors

arduino-cli compile -b arduino:mbed:pico -v PWM_Test
...
PWM_Test/commands.ino:522:17: error: 'analogWriteFreq' was not declared in this scope
                 analogWriteFreq(duty);
                 ^~~~~~~~~~~~~~~
PWM_Test/commands.ino:522:17: note: suggested alternative: 'analogWrite'
                 analogWriteFreq(duty);
                 ^~~~~~~~~~~~~~~
                 analogWrite
PWM_Test/commands.ino:534:17: error: 'analogWriteRange' was not declared in this scope
                 analogWriteRange(duty);
                 ^~~~~~~~~~~~~~~~
PWM_Test/commands.ino:534:17: note: suggested alternative: 'analogWrite'
                 analogWriteRange(duty);
                 ^~~~~~~~~~~~~~~~

Please provide a working test sketch including a details description of which tooling you used how to compile it.

dlkeng commented 1 year ago

Alex,

I am compiling this on a Windows 10 Pro machine in the Arduino IDE Version 1.18.13 using "Arduino Mbed OS RP2040" V3.5.4.

The original supplied code included the #defines so that I could use the Pico or the Pico W and either the Arduino Mbed core or the Philhower Arduino-Pico core. I get no compiler errors. I don't use the CLI so maybe the GUI IDE is adding defines that the code was looking for.

However, to simplify things, I have changed the PWM_Test code to remove all of the #defines and associated #ifdefs to compile for the Arduino Mbed core, which is where the issues are occurring. You can get this version from my Dropbox at the following link: PWM_Test2

Also included in the download is the executable: PWM_Test2.ino.uf2 This can be copied to the Pico's file system with the BOOTSEL process in case you still have problems compiling in your environment.

Dan

aentinger commented 1 year ago

The mystery has been uncovered. Apparently we (Arduino) are splitting the support for the RP2040 Pico into a separate deployed core arduino:mbed_rp2040.

This is how to install/compile using arduino-cli:

arduino-cli core update-index
arduino-cli core install arduino:mbed_rp2040
arduino-cli compile -b arduino:mbed_rp2040:pico -v PWM_Test2
aentinger commented 1 year ago

Hi @dlkeng I believe I've fixed one of your issues (the one with PWM not working after configuring a GPIO), see #620 .

I'll attach an UTF2 file of your test application compiled with the new core here: can you please test it?

PWM_Test2.zip

dlkeng commented 1 year ago

Alex,

Yes, I can confirm your attached UTF2 file appears to correct the operations of Issue 2 and Issue 3 of this problem report.

Dan

aentinger commented 1 year ago

Thank you for the confirmation. I've got another file for you to test, this one should eliminate issue 1:

PWM_Test2.ino.zip

Edit: This is related to https://github.com/arduino/mbed-os/pull/30/files .

dlkeng commented 1 year ago

Alex,

Yes, I can confirm your latest UTF2 file fixes the Issue 1 of this problem report. All items now appear to be corrected.

Thanks, Dan

aentinger commented 1 year ago

Thank you :wave: :rocket:

CorsairCat commented 1 month ago

Hi, @aentinger I just came into same issue on Giga and looked into the library, I noticed that it is the not set status of digitalPinToGpio(pin) and digitalPinToPwm(pin), which makes both the digitalWrite and analogWrite functions only change the output of that certain Mbed pin object but not the output method to the correct one. I just notice this pull request and wondering why it is still not merged into the main branch while it solved this issue more than a year ago? Thanks for the help.