earlephilhower / arduino-pico

Raspberry Pi Pico Arduino core, for all RP2040 and RP2350 boards
GNU Lesser General Public License v2.1
2.06k stars 431 forks source link

[Q] Redefine SPI-Pins for supported Board "Cytron Maker Pi Pico" #851

Closed guidol70 closed 2 years ago

guidol70 commented 2 years ago

A user of mine project "RunCPM for Pico" would use the onboard SD-Card of the Cytron Maker Pi Pico: https://github.com/guidol70/RunCPM_RPi_Pico/issues/1

In the variants cytron_maker_pi_rp2040\pins_arduino.h the follwing is defined:

// SPI (Not pinned out)
#define PIN_SPI1_MISO       (31u)
#define PIN_SPI1_MOSI       (31u)
#define PIN_SPI1_SCK        (31u)
#define PIN_SPI1_SS         (31u)
#define SPI_HOWMANY         (0u)

But for accesing the onboard SD-Card - I think he need somehting like:

#define PIN_SPI1_MISO       (11u)
#define PIN_SPI1_MOSI       (12u)
#define PIN_SPI1_SCK        (10u)
#define PIN_SPI1_SS         (15u)
#define SPI_HOWMANY         (1u)

Is there a way to reconfigure this "on the fly" in the .ino or is the only possible solution to change the pins_arduino.h? He also need to find out how to use SPI1 and not SPI0 with SdFat- so I think about something like SPI pin selection for SD https://github.com/earlephilhower/arduino-pico/issues/758#issuecomment-1214425993

Maker_Pico_SPI

earlephilhower commented 2 years ago

Is that the official pinout? Should we change the board definition? It's simple to update...

OTW, you can use the SPI1.setXXX calls listed here: https://arduino-pico.readthedocs.io/en/latest/pins.html#spi-spi0-spi1-spi1

guidol70 commented 2 years ago

Is that the official pinout? Should we change the board definition? It's simple to update...

the pinout for the SDcard of the Cytron Make Pi Pico is from the companys own pdf-datasheet on their web-page

Direct Link to the PDF on this page

OTW, you can use the SPI1.setXXX calls listed here: https://arduino-pico.readthedocs.io/en/latest/pins.html#spi-spi0-spi1-spi1

Thanks:) this mean he should/could may use ( does this work with the original SDFat-Library? or only with your SDFS?)

void setup() {
  SPI1.setRX(11);
  SPI1.setCS(15);
  SPI1.setSCK(10);
  SPI1.setTX(12);
}
SD.begin(15, SPI1);
guidol70 commented 2 years ago

I did try to compile such a config - worked for SPI (0), after creating a ESP8266SdFat.h which has the following code (to use your SdFat.h and not the original Greiman) #include "SdFat.h" in the Library Folder C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\ESP8266SdFat\src But SD.begin wouldnt recognize the SPI1 as argument :(

  SPI1.setRX(11);   // MISO
  SPI1.setCS(15);   // Card Select
  SPI1.setSCK(10);  // Clock
  SPI1.setTX(12);   // MOSI

SD.begin(15,SPI1)
Q:\1A_RunCPM\RunCPM_v5_7_master_28092021\RunCPM-master\RunCPM_Pico_21082025_SD_MakerPiPico\RunCPM_Pico_21082025_SD_MakerPiPico.ino: In function 'void setup()':
RunCPM_Pico_21082025_SD_MakerPiPico:156:22: error: no matching function for call to 'SdFat32::begin(int, SPIClassRP2040&)'
  156 |   if (SD.begin(15,SPI1)) {
      |                      ^
In file included from C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\ESP8266SdFat\src/ESP8266SdFat.h:1,
                 from Q:\1A_RunCPM\RunCPM_v5_7_master_28092021\RunCPM-master\RunCPM_Pico_21082025_SD_MakerPiPico\RunCPM_Pico_21082025_SD_MakerPiPico.ino:32:
C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\ESP8266SdFat\src/SdFat.h:58:8: note: candidate: 'bool SdBase<Vol>::begin(SdCsPin_t) [with Vol = FatVolume; SdCsPin_t = unsigned char]'
   58 |   bool begin(SdCsPin_t csPin = SS) {
      |        ^~~~~
C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\ESP8266SdFat\src/SdFat.h:58:8: note:   candidate expects 1 argument, 2 provided
C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\ESP8266SdFat\src/SdFat.h:73:8: note: candidate: 'bool SdBase<Vol>::begin(SdCsPin_t, uint32_t) [with Vol = FatVolume; SdCsPin_t = unsigned char; uint32_t = long unsigned int]'
   73 |   bool begin(SdCsPin_t csPin, uint32_t maxSck) {
      |        ^~~~~
C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\ESP8266SdFat\src/SdFat.h:73:40: note:   no known conversion for argument 2 from 'SPIClassRP2040' to 'uint32_t' {aka 'long unsigned int'}
   73 |   bool begin(SdCsPin_t csPin, uint32_t maxSck) {
      |                               ~~~~~~~~~^~~~~~
C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\ESP8266SdFat\src/SdFat.h:82:8: note: candidate: 'bool SdBase<Vol>::begin(SdSpiConfig) [with Vol = FatVolume]'
   82 |   bool begin(SdSpiConfig spiConfig) {
      |        ^~~~~
C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\ESP8266SdFat\src/SdFat.h:82:8: note:   candidate expects 1 argument, 2 provided
C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\ESP8266SdFat\src/SdFat.h:91:8: note: candidate: 'bool SdBase<Vol>::begin(SdioConfig) [with Vol = FatVolume]'
   91 |   bool begin(SdioConfig sdioConfig) {
      |        ^~~~~
C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\ESP8266SdFat\src/SdFat.h:91:8: note:   candidate expects 1 argument, 2 provided
Using library SPI at version 1.0 in folder: C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\SPI 
Using library ESP8266SdFat at version 2.1.1 in folder: C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\ESP8266SdFat 
exit status 1
no matching function for call to 'SdFat32::begin(int, SPIClassRP2040&)'
earlephilhower commented 2 years ago

Use this begin call: https://github.com/earlephilhower/arduino-pico/blob/91b4bdb58f5f1ed7bdcd6b27a1eebc2d6f5a4056/libraries/SD/src/SD.h#L38

SD.begin(pin, SPI_HALF_SPEED, SPI1)

guidol70 commented 2 years ago

SPI_HALF_SPEED, SPI1 This doenst seem to like me :(

Q:\1A_RunCPM\RunCPM_v5_7_master_28092021\RunCPM-master\RunCPM_Pico_21082025_SD_MakerPiPico\RunCPM_Pico_21082025_SD_MakerPiPico.ino: In function 'void setup()':
RunCPM_Pico_21082025_SD_MakerPiPico:157:40: error: no matching function for call to 'SdFat32::begin(int, long unsigned int, SPIClassRP2040&)'
  157 |   if (SD.begin(15, SPI_HALF_SPEED, SPI1)) {
      |                                        ^
earlephilhower commented 2 years ago

It looks like you're running a different SD library. Can you double check you're not running an external verino of SdFat or SD? Compile logs should have that info.

The Pico needs the custom versions of those two libs shipped with the core (to integrate with the File infrastructure we have).

earlephilhower commented 2 years ago

Also, can you give an MCVE for your failing compile with the SPI1 option? I don't actually understand the error you're seeing referencing SdFat::...

guidol70 commented 2 years ago

It looks like you're running a different SD library. Can you double check you're not running an external verino of SdFat or SD? Compile logs should have that info.

for the dedicated use of the ESP8266SdFat I created (as I did wrote before): ESP8266SdFat.h which has the following code (to use your SdFat.h and not the original Greiman) #include "SdFat.h" in the Library Folder C:\Users\guido\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\2.5.2\libraries\ESP8266SdFat\src because for other systems (AVR/AVR32/STM32/ESP32/ESP8266) I do use the original SdFat from Greiman (all systems are installed in my Arduino IDE)

I also got the original SdFat v2.2.0 installed, but with #include <ESP8266SdFat.h> I do get Using library ESP8266SdFat at version 2.1.1

SD.begin(15, SPI_HALF_SPEED, SPI1) didnt worked (as I had these stange error as written above) BUT I did found a workaround (another form of the command/init) at Greimans SdFat github-Issue #285 which did lead me to the following code - which compiles successfully ;)

// =============================================================
// Set the SPI1 Pins
// =============================================================
 SPI1.setRX(11);   // MISO
 SPI1.setCS(15);   // Card Select
 SPI1.setSCK(10);  // Clock
 SPI1.setTX(12);   // MOSI

// =============================================================
// Setup SD card writing settings
// =============================================================
#define SPI_SPEED SPI_FULL_SPEED  
#define SD_CONFIG SdSpiConfig(15, DEDICATED_SPI, SPI_FULL_SPEED, &SPI1)

// =============================================================
// Start accessing the SD card
// =============================================================
if (SD.begin(SD_CONFIG)) {
earlephilhower commented 2 years ago

Very odd. I'm still traveling so don't have access to my dev system, but when I get back this weekend I'll give it a try and see if I can make it fail to compile like you were seeing.

guidol70 commented 2 years ago

I reworked the "source" to a (final) code which I could use (with other pin numbers or spi-bus) also on the normal Rpi Pico, The RC2040 Pico and the Cytron Maker Pi Pico ;)

It looks like :

// ====================================================================
// Redefine SPI-Pins - if needed : (SPI.) = SPI0 / (SPI1.) = SPI1
// ====================================================================
  SPI1.setRX(11);   // MISO
  SPI1.setCS(15);   // Card Select
  SPI1.setSCK(10);  // Clock
  SPI1.setTX(12);   // MOSI

// ====================================================================
// Setup SD card writing settings
// Info at: https://github.com/greiman/SdFat/issues/285#issuecomment-823562829
// ====================================================================

// older SDINIT config
#define SDINIT SS, SD_SCK_MHZ(SDMHZ)

// #define SPI_SPEED SPI_FULL_SPEED           // full speed is 50Mhz - to fast for the most SDCard
// #define SPI_FULL_SPEED SD_SCK_MHZ(50)      // full speed is 50Mhz - to fast for the most SDCard

// older SD_CONFIG sample
// #define SD_CONFIG SdSpiConfig(5, DEDICATED_SPI, SPI_FULL_SPEED, &SPI)

// ====================================================================
// NEW SD_CONFIG formerly SDINIT
// Info at: https://github.com/greiman/SdFat/issues/285#issuecomment-823562829
// ====================================================================
#define SDFAT_FILE_TYPE 1           // Uncomment for Due, Teensy or RPi Pico
#define ENABLE_DEDICATED_SPI 1      // Dedicated SPI 1=ON 0=OFF
#define SDMHZ_TXT "19"              // for outputing SDMHZ-Text
#define SDMHZ 19                    // setting 19 Mhz for SPI-Bus
// normal is 12Mhz because of https://www.pschatzmann.ch/home/2021/03/14/rasperry-pico-with-the-sdfat-library/
#define SS 15
// select required SPI-Bus : (&SPI) = SPI0 / (&SPI1) = SPI1
#define SD_CONFIG SdSpiConfig(SS, DEDICATED_SPI, SD_SCK_MHZ(SDMHZ), &SPI1)
// ====================================================================

if (SD.begin(SD_CONFIG)) {
earlephilhower commented 2 years ago

I just built the following w/o any errors using the git master branch:

#include <SD.h>
#include <SPI.h>

void setup() {
  SD.begin(2,SPI_FULL_SPEED,SPI1);
}

void loop() {
}

So, maybe you're pulling in an incompatible SD library? That library also has to come from the repo, not from Adafruit or Arduino, or it won't have the add'l SPI object configuration parameter.

guidol70 commented 2 years ago

So, maybe you're pulling in an incompatible SD library? That library also has to come from the repo, not from Adafruit or Arduino, or it won't have the add'l SPI object configuration parameter.

I installed/created a fresh portable Arduino IDE Instance v1.8.19 and installed there only your arduino-core RP2040 additiionally.

You code above compiled without errors - like on your side. So I found the difference -in the Code I use for RunCPM (isnt created by myself), but has been created in the past so for historycal reasons? I think they moved in the past from SD to SdFat and added the "alias"

The minimal sourcecode which gives me the error: no matching function for call to 'SdFat32 is

#include <SdFat.h>
#include <SPI.h>

SdFat SD;

void setup() {
  SD.begin(2,SPI_FULL_SPEED,SPI1);
}

void loop() {
}

So no "incompatible SD library" is installed, but this alias does create some kind of loop/replacement which doenst work with my (which I only use and didnt create) code :(

earlephilhower commented 2 years ago

That explains the weird error! In any case, your use of the SPI1 in the config options is the only way to use it given the code you've got to work with, so that seems fine. I will add the SPI1 pinout to the Cytron variant.h and we'll be done here. Thx!