Thanks to visit codestin.com
Credit goes to github.com

Skip to content

RP2: 1us glitch on SCK pin when switching from SPI function to Pin.OUT #10226

Closed
@pdg137

Description

@pdg137

On the RP2040, several sets of pins can be selected for each of the two SPI modules. Sometimes we need to disable the SPI function of a pin, while leaving it in the state it was in. For example the following code should leave pin 14 (SCK) low between write() and sck(1):

from machine import SPI, Pin

sck = Pin(14)
mosi = Pin(15)
spi = SPI(id=1, baudrate=100000, polarity=0, phase=0, sck=sck, mosi=mosi)
spi.write(bytearray([0xAA]))
sck.init(mode=Pin.OUT, value=0)
sck(1)

However, the first time it runs after reset, there's a ~1 microsecond glitch during which pin 14 floats upward. The glitch causes unreliable behavior with SPI devices if you don't take measures to avoid it (the workaround is to run sck.init(mode=Pin.OUT, value=0) at least once before using SPI.)

I tested this on the latest master branch, MicroPython v1.19.1-716-g227ea47f4, with a Raspberry Pi Pico having a 1k pull-up on pin 14. Here is a trace of the output:

We can zoom in on it:

I believe the source of the problem is here:

https://github.com/micropython/micropython/blob/master/ports/rp2/mphalport.h#L99-L103

static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) {
    gpio_set_function(pin, GPIO_FUNC_SIO);
    gpio_set_dir(pin, GPIO_OUT);
    machine_pin_open_drain_mask &= ~(1 << pin);
}

The SPI alternate function is disabled before the pin is set to an output.

I don't quite understand what's going on here, but I believe that switching the order of these operations would let it work as intended. Is there a reason to do them in this order? Or is there some other problem?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions