SPI: SCLK polarity (CPOL) is inverted #1583
Labels
No labels
bazel
bluetooth
board settings
boot_stage2
bug
build
c++
can't reproduce
clang
clib-interface
cmsis
code cleanliness
code size
compiler version issues
cyw43_driver
debug
discussion
documentation
duplicate
dynamic_clock
elf2uf2
enhancement
errata
filesystem
flash layout
floating point
FreeRTOS
hardware_adc
hardware_claim
hardware_clocks
hardware_dma
hardware_exception
hardware_flash
hardware_gpio
hardware_i2c
hardware_irq
hardware_pio
hardware_pwm
hardware_rcp
hardware_rtc
hardware_spi
hardware_sync
hardware_uart
hardware_vreg
hardware_watchdog
hardware_xosc
help wanted
host
IAR
installation
invalid
linker scripts
lto
lwip
mbedtls
missing API
needs reporter detail
networking
newlib
newlib-multicore
non-c
non-cmake
non-gcc
openocd
orphan PR
OS integration
pico_async_context
pico_base
pico_binary_info
pico_flash
picolibc
pico_lwip
pico_malloc
pico_multicore
pico_printf
pico_runtime
pico_stdio
pico_stdio_usb
pico_sync
pico_time
pico_util
pioasm
port
question
review
review2
rtos interop
runtime init
static library
svd
test
tinyusb
vscode
wifi integration
wontfix
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-raspberrypi/pico-sdk#1583
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
(derived from https://github.com/earlephilhower/arduino-pico/issues/1900)
Wikipedia says
so for CPOL = 0, the SCLK pin should idle LOW before and after a SPI transfer.
However, testing with
I see
on GP2, 3, 4 and 5 respectively. This is exactly inverted, it idles HIGH. Wut?
Note that changing to
SPI_CPOL_1in the above example will make the clock idle low, which is again opposite to how it should be. No matter what, in my logic analyzer, I always have to select the opposite SPI mode / clock polarity than what I set in the code to make it decodable.Push.
Sorry it took so long. I ran your code on rp2040 (and rp2350) and it seems to work correctly. So I'm at a bit of a loss why you're seeing that. Screen grab is where SPI_CPOL_0. If I change to SPI_CPOL_1 it uses clock idle high.

Checked again - seems to work ok for me. Mysterious!
Have there been multiple revisions of the RP2040 silicon, and this only happens on the older one? I'm very sure I measured this correctly on my board. Any way to read out the silicon rev from a register?
Yes. I would expect the following to show "2"
chip_version.zip
chip_version.uf2.zip
Running this on my Pico, I get
though. Is that SPI thing a known errata there?
No, the only non-ROM change between B1 and B2 was fixing the USB enumeration erratum (RP2040-E5)
I've manged to find B0 and B1 devices (can you check what you have by takin a photo of the text on the chip?) and it still appears as if CPOL works correctly. So I still don't understand what you're seeing. I was seeing CS behaving oddly on my B0 but changing it to GP1 fixed that - maybe just dodgy solder on this device? You could try using GP6 for the SPI0 clock or switch to SPI1 (e.g. GP10-13?). Just to see if the other peripheral behaves the same.
I've been experiencing similar behavior where a Pico 1 board in SPI slave mode has to have CPOL and CPHA set oposite to what the master (Pico 2 in my case) has set in order to decode bits correctly.
Happy to do some testing with my available boards.
I'll try to come back and add some results of those tests in the next few days.
@jakerr Can you take a photo of the top of the chip? How old is the Pico 1?
Here's the patient. This is the best photo I could get with my poor phone camera.
Can you make out everything you need?
It's a Pico H ©2021
I think the chip says "RP2-B2 21/36"
It would be "interesting" if you could run the uf2 here https://github.com/user-attachments/files/17651433/chip_version.uf2.zip
Just to rule out the chip version. I have a Pico H that looks the same as yours.
And my Pico H is working ok...
@peterharperuk Thanks very much for testing this again.
I've run the code in this issue and the chip id snippet ("Chip version 2") and determined that in master mode my chip is behaving as specified in the datasheet. Sorry for the confusion.
That said I still do have the issue that the polarity and phase must be swapped in slave mode in order for it to properly decode received data. I will keep looking into that and file a new issue if I can discover a reproducible case.
I also did some consistency checking to make sure the set
spi_set_formatwas having the expected effect on the spi cr0 register and that all looked fine to me.SPI_POL_0, SPI_CPHA_0:


SPI_POL_1, SPI_CPHA_1:
I tried this test on the pins in the original issue:
and also on these pins:
The result was the same.
Ok, I'll check slave mode.
Hi @peterharperuk,
Thank you. Before sending you down that rabbit hole, I did some investigation today and think I've convinced myself that, at least the board I have, is behaving as specified.
I want to do a more thorough write up with some sample code for the next person that needs to investigate,
but here's what I discovered, briefly:
I was driving the communication from a pico 2 running in master mode and:
SPI_POL_0, SPI_CPHA_0but without enabling the SPI function for the CS (Chip Select) pin.I was driving the CS pin from software and sending it low for the duration of a transfer.
The thing I did wrong was failed to implement the pulse between words of the multi word
transfer that is required by the two modes that have
SPI_CPHA_0.So my communication of two words consecutively looked like this:
But should have been:
So I was saying the host is MODE_0 but it was actually more like MODE_2 or MODE_4 in its behavior (though with reversed polarity), so it's unsurprising that this was producing strange results.
The surprising thing was setting the slave to
SPI_POL_1, SPI_CPHA_1while in that mode, the slave was able to adapt to the master's behavior becauseat least the transaction framing was as expected for SPI_CPHA_1.
I suppose the slave peripheral adapted to the inverted phase of my invalid mode.
Looking at https://www.raspberrypi.com/documentation/microcontrollers/pico-series.html#pinout-and-design-files-3 says that GP3 is SPI0 TX, i.e. the output from the SPI block. IIIRC this means that if you're running the SPI in master mode, then GP3 is MOSI; but if you're running the SPI in slave mode then GP3 is MISO. (Although I dunno if this has any bearing on the problem being discussed here or not?)
I think SDO is less confusing. Presumably this is the case or else it wouldn't work at all.
MOSI (GP3) -> SDI (GP4)
MISO (GP4) <- SDO (GP3)