Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
dlkeng opened this issue Jan 28, 2023 · 11 comments · May be fixed by #620
Open

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

dlkeng opened this issue Jan 28, 2023 · 11 comments · May be fixed by #620
Assignees
Labels
bug Something isn't working RP2040

Comments

@dlkeng
Copy link

dlkeng commented Jan 28, 2023

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:

  • When doing an analogWrite() to a GPIO pin with an adjacent GPIO pin on the same PWM slice with
    an active PWM already, the adjacent pin's PWM stops
    • Example: (GP2 and GP3 using PWM slice # 1)
      1. Reset Pico // always start from known state
      2. analogWrite(2, 64) // pin GP2 starts at 25% PWM output
      3. analogWrite(3, 128) // pin GP3 starts 50% PWM output, but GP2 stops it's PWM output
        Work-around:
      4. analogWrite(2, 192) // pin GP2 now restarts with 75% PWM output
        This appears to be due to the setting of the companion pin causes the CC register counter
        compare value for the 1st pin to be set to 0. In the above example, reversing the order
        of the pins (i.e. GP3, then GP2) still shows the same problem. Once both pins are outputting
        a PWM signal, either one can be modified without affecting the other pin's output.

Issue 2:

  • After changing a GPIO pin with an active analogWrite() PWM output to a digitalWrite()
    digital output, attempting to then change the pin to an analogWrite() PWM output fails
    to output the PWM signal.
    • Example: (GP2 using PWM slice # 1)
      1. Reset Pico // always start from known state
      2. analogWrite(2, 64) // pin GP2 starts PWM output
      3. digitalWrite(2, 1) // pin GP2 digital output high
      4. analogWrite(2, 128) // pin GP2 fails PWM output
        Work-around:
      5. gpio_set_function(2, GPIO_FUNC_PWM) // re-activate pin GP2 PWM output
      6. analogWrite(2, 32) // change pin GP2 PWM output
      7. digitalWrite(2, 0) // pin GP2 fails digital output, but remains PWM output
        This appears to be due to not automatically changing the pin's function from PWM to SIO.
        Any subsequent changes to the pin's digital or analog output also requires changing the
        pin's mode manually.

Issue 3:

  • After changing a GPIO pin with a digitalWrite() digital output to an analogWrite()
    PWM output, attempting to then change the pin to an digitalWrite() digital output fails
    to output the digital signal level.
    • Example: (GP2 using PWM slice # 1)
      1. Reset Pico // always start from known state
      2. digitalWrite(2, 1) // pin GP2 digital output high
      3. analogWrite(2, 64) // pin GP2 starts PWM output
      4. digitalWrite(2, 1) // pin GP2 fails digital output, but remains PWM output
        Work-around:
      5. pinMode(2, OUTPUT) // pin GP2 digital output low
      6. digitalWrite(2, 1) // change pin GP2 digital output high
      7. analogWrite(2, 32) // pin GP2 fails PWM output, but remains digital output
        This appears to be due to not automatically changing the pin's function from SIO to PWM.
        Any subsequent changes to the pin's digital or analog output also requires changing the
        pin's mode manually.

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

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

@facchinm facchinm added bug Something isn't working RP2040 labels Jan 30, 2023
@aentinger
Copy link
Contributor

Hi @dlkeng ☕ 👋

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

Cheers, Alex

@dlkeng
Copy link
Author

dlkeng commented Feb 6, 2023

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
Copy link
Contributor

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
Copy link
Author

dlkeng commented Feb 7, 2023

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
Copy link
Contributor

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
Copy link
Contributor

aentinger commented Feb 8, 2023

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
Copy link
Author

dlkeng commented Feb 8, 2023

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
Copy link
Contributor

aentinger commented Feb 13, 2023

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
Copy link
Author

dlkeng commented Feb 13, 2023

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
Copy link
Contributor

Thank you 👋 🚀

@CorsairCat
Copy link

CorsairCat commented Oct 5, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working RP2040
Projects
None yet
4 participants