Tiny 2040 SPI not working with Arduino/C

Hi,
I can’t get the SPI connection of the Tiny 2040 to work with Arduino/C++. I don’t post code here since I’ve already tested lots of pin combinations, to no effect.
Does anyone know whether the Tiny 2040 pinout diagram is correct? I see several threads here where people need to use totally arbitrary SPI pin combinations, albeit with CircuitPython/MicroPython.
Pimoroni, can you please help here? Is the pinout diagram of the Tiny 2040 proven to be correct and compatible with Arduino SPI libraries? What are the correct initialization steps? Maybe the board designer knows? It seems lots of people are having trouble getting SPI to work with the Tiny 2040, which is utterly annoying, to be frank.
Thanks for any help!

Hi,

Sorry to hear about your issue. I am unfamiliar with the Arduino C support for RP2040, only the Pico SDK C. Is that official support provided by Arduino?

Does anyone know whether the Tiny 2040 pinout diagram is correct?

Pimoroni, can you please help here? Is the pinout diagram of the Tiny 2040 proven to be correct and compatible with Arduino SPI libraries?

I can confirm that the Tiny 2040’s pinout diagram is correct. GP0-7 are exposed on the right hand side, giving access to SPI0 in various combinations. Remember that SPI TX was formerly MOSI, and RX was formerly MISO.

I cannot comment on whether the pinout is compatible with the Arduino SPI libraries. You will have to raise that with them.

I see several threads here where people need to use totally arbitrary SPI pin combinations, albeit with CircuitPython/MicroPython.

RP2040 is a very flexible chip, so seeing people use different SPI pin combinations based on their particular projects is not surprising.

What are the correct initialization steps? Maybe the board designer knows?

Again, I am not familiar with Arduino C support for RP2040, but it should be no different from using any other SPI pins on a Pico-based board. In fact, if someone has Arduino C and a Pico could they test the SPI on its GP0 to GP7 pins and report back?

It seems lots of people are having trouble getting SPI to work with the Tiny 2040, which is utterly annoying, to be frank.

Could you point us to these reports please? I checked with support and they are not aware of any issues having been raised.

Thanks a lot for stepping in! The core I’m using is the recommended one by Earle Philhower, and the Tiny2040 is on the compatibilty list.

The other posts referring to SPI pin problems are these:
https://forums.pimoroni.com/t/which-are-the-spi-pins-on-tiny-2040/17450/16
https://forums.pimoroni.com/t/tiny-2040-display-watch/17843/24?page=2

Especially the latter one drove me to think the pinout diagram might not be correct. People seem to try and connect just about every pin arbitrarily to get things to work, even with Python.

I’m well aware the pin flexibility of the RP2040 introduces some difficulties and is confusing many people including me. Sadly, support for the C/C++ side looks rather sparse since a majority of people seems to use the chip with Micropython/CircuitPython. That makes good sense, but my problem in question circles around the RFM69 implementation in Python which is based on the RadioHead communication settings, which in turn are not compatible with the LowPowerLab approach, while the RadioHead library is reported to have some bugs in certain environments…

So for my setup I’m forced to utilize C/C++ right now - and I’m wondering if I miss SPI init steps here, because the information available on how to use SPI (and interrupts) with the RP2040 in the C/C++ environment looks somewhat unambiguous to me.
I understand the pins GP0 to GP7 can utilize SPI0. But do I have to somehow introduce the pins I use to the SPI libraries? Are all of these pins mapped automatically to hardware SPI0, so I don’t need to map anything first? I also understand the pins “GP…” need to be named just by their number in the Arduino C/C++ environment - or do they?

Any distinct advice would be greatly appreciated. I’m also well aware the mistake might lie somewhere deep in my setup which is difficult to test or just within my stupidity, but I’ve had success with a Feather M4 as well as with the ItsyBitsy NRF52840 - so getting things to work with the RP2040 seems to be unusually hard, and as already stated, documentation on the C/C++ side seems much less accessible to me than for other chips or RP2040 Python environments. Please excuse my frustrated post - I’ve just tried so many things (maybe too many) and scraped so many websites on this that I’m on the verge of giving up trying to utilize the Tiny 2040 with C/C++.

Both of those threads linked boiled down to people trying to initialise SPI1, using the SPI0 pins - and reported things working once they fixed that?

In the absence of code and error codes, we’re shooting in the dark somewhat, though!

What I’m trying to find - and can’t, maybe that’s just me - is the information whether the pins 0 to 7 are tied to hardware SPI0 by default or not - and in which way.

Could I use, say, pins GP0 and GP1 as RX and CS and together with these GP6 and GP7 as CLK and TX? Or - what one would think intuitively - do I mandatory have to use GP2 and GP3 for that when using 0 and 1 as RX and CS? Will the next four pins (4 to 7) work together as well in the same way?

I just cannot get around the barrier that eight pins are marked for only four SPI “channels” of SPI0. Which ones do I have to use? Or am I free to decide? Do I have to assign them in some way, as far as C/C++/the Arduino workflow is concerned? I really tried to figure that out, but I couldn’t. What does it mean that two sets of four pins may be/must be SPI0?
Internally, I may be free to assign all that by writing numbers to some registers - but what is the simple default setup for the C/C++ core?

If anyone can point me to that information I would be really grateful because I think that’s what it’s all about - someone saying: “Yes, you can just use pins 0 to 3 for the SPI0 channels marked accordingly on the pinout diagram without further configuration” - or something else, if that’s not the case.

Again, help on this is really appreciated! Thank you for looking into this thread.

The Arduino docs on SPI that you can set the SPI pins to whichever pins you require - so any of the ones on the pinout provided.

Again, without details of code and/or error it’s very hard to say much more - you might get more traction with questions about Arduino workflows on the Arduino boards?

Thanks for your answer - I’ve actually been on that page. Reading that one would think I could even assign pin 0 to, say, CLK. But is that true? Why are the pins 0 to 3 marked for specific channels, then?
The thing is: If I don’t know all that for sure I cannot really search for my mistakes.

(I also visited the Arduino SPI page which says the “Nano” board - and there is one with the RP2040 - uses pins 11, 12 and 13 by default, so I would have to reassign them. But, sadly, there is no page that unmistakenly says “to use SPI with the Pimoroni Tiny 2040 in the Arduino environment you must assign pins 0 to 3 or 4 to 7 to the channels marked on the pinout diagram”.)

Thanks for looking into this, I probably can’t get any further. BTW, sadly, C/C++ programs do not fail with error codes, they just crash the board or do not talk to peripherals and one does not know what went wrong with just one look. (Also, SPI.begin() does not return any error codes.)

Well I’d stick to the channel assignments on the pinout - so I’d keep to GP2/GP6 for SCK unless you have an incredibly good reason to try to ignore the pinout?

Again, there’s nothing magical about the Tiny2040; it’s just a regular ol’ RP2040 in a petite package. Even the GPIO pin numbers are the same (a standard Pico, for example, also offers up SPI0 on GPIO0-3 and 4-7). Even the Nano you’re referring to is the same - physical pins 11/12/13 on there are GPIO7/5/6 (which is… confusing, but still).

Months later I came back to this problem - and finally solved it. I write the solution down here to help others who might be stuck with that very same phenomenon.

It’s true that the pin numbers that need to be given in the Arduino-C/C++ code correspond to the numbers with the “GP” prefix on the pinout diagram (thanks for your help and clarification).
But that’s not the end of the story. Using the well-known RP2040 core by Earle Philhower which supports the Tiny2040 by Pimoroni, it is still mandatory to explicitly set the pin numbers the SPI bus 0 (within your code just called SPI without the zero) should use, i.e. GP0 for RX (formerly MISO) and so on, according to the diagram.
To do this, one has to specify these pins mandatory within Arduino’s “setup” function before calling SPI.begin (or before any other library utilizing the SPI bus will call SPI.begin).
So include code like the following within “setup ()” (assuming you have included <SPI.h> somewhere at the very beginning of your code):

SPI.setRX(0);
SPI.setCS(1);
SPI.setSCK(2);
SPI.setTX(3);

For some reason unknown to me these pins are not predefined for the SPI hardware bus (= SPI 0) of the Tiny2040. They are probably set to the original Pi Pico 2040 SPI 0 pins - even if the aforementioned RP2040 core is said to support the Tiny2040. That is certainly true, but sadly it does not apply to the SPI pin numbers the RP2040 core uses by default when compiling for the Tiny2040, so it seems the core doesn’t differentiate between the Pi Pico and the Tiny2040 automatically, at least concerning the SPI bus.

Maybe this was obvious to anyone else but me.