Open
Description
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)
- Reset Pico
// always start from known state
- analogWrite(2, 64)
// pin GP2 starts at 25% PWM output
- analogWrite(3, 128)
// pin GP3 starts 50% PWM output, but GP2 stops it's PWM output
Work-around: - 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.
- Reset Pico
- Example: (GP2 and GP3 using PWM slice # 1)
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)
- Reset Pico
// always start from known state
- analogWrite(2, 64)
// pin GP2 starts PWM output
- digitalWrite(2, 1)
// pin GP2 digital output high
- analogWrite(2, 128)
// pin GP2 fails PWM output
Work-around: - gpio_set_function(2, GPIO_FUNC_PWM)
// re-activate pin GP2 PWM output
- analogWrite(2, 32)
// change pin GP2 PWM output
- 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.
- Reset Pico
- Example: (GP2 using PWM slice # 1)
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)
- Reset Pico
// always start from known state
- digitalWrite(2, 1)
// pin GP2 digital output high
- analogWrite(2, 64)
// pin GP2 starts PWM output
- digitalWrite(2, 1)
// pin GP2 fails digital output, but remains PWM output
Work-around: - pinMode(2, OUTPUT)
// pin GP2 digital output low
- digitalWrite(2, 1)
// change pin GP2 digital output high
- 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.
- Reset Pico
- Example: (GP2 using PWM slice # 1)
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
--------------------------------------------------------------------------------------------