SDcard support for RPI pico?


#1

Hi David,

I’m trying to add sdcard support for the polular rpi pico , but no succes so far.
This is for now what I tried : (see the 5 lines). It’s a guess to undefine the littlefs …

#elif defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_QTPY_RP2040) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || defined(ARDUINO_SEEED_XIAO_RP2040)
#define WORKSPACESIZE (22912-SDSIZE) /* Objects (8bytes) /
//#define LITTLEFS
** //#include <LittleFS.h>
*
** //#define FILE_WRITE_BEGIN “w”**
** //#define FILE_READ “r”**
#define SDCARD_SS_PIN 16
#define CODESIZE 256 /
Bytes */
#define STACKDIFF 320
#define CPU_RP2040
#if defined(gfxsupport)
const int COLOR_WHITE = 0xffff, COLOR_BLACK = 0;
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
Adafruit_ST7789 tft = Adafruit_ST7789(5, 1, 3, 2, 0); // TTGO RP2040 TFT
#define TFT_BACKLIGHT 4
#define TFT_I2C_POWER 22
#endif

This however seems to yield to errors , as shown here :

In file included from /home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/libraries/SD/src/SD.h:23,
from /home/ronny/Arduino/ulisp_arm_4.5/ulisp_arm_4.5.ino:32:
/home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/cores/rp2040/FS.h: In instantiation of ‘size_t fs::File::write(T&) [with T = char; size_t = unsigned int]’:
/home/ronny/Arduino/ulisp_arm_4.5/ulisp_arm_4.5.ino:2278:47: required from here
/home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/cores/rp2040/FS.h:96:28: error: request for member ‘available’ in ‘src’, which is of non-class type ‘char’
96 | while ((size_t)src.available() > sizeof(obuf)) {
| ^~~~~
/home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/cores/rp2040/FS.h:97:17: error: request for member ‘read’ in ‘src’, which is of non-class type ‘char’
97 | src.read(obuf, sizeof(obuf));
| ^~
/home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/cores/rp2040/FS.h:105:30: error: request for member ‘available’ in ‘src’, which is of non-class type ‘char’
105 | size_t leftLen = src.available();
| ^
~~
/home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/cores/rp2040/FS.h:106:13: error: request for member ‘read’ in ‘src’, which is of non-class type ‘char’
106 | src.read(obuf, leftLen);
| ~~^~
Multiple libraries were found for “SD.h”
Used: /home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/libraries/SD
Not used: /home/ronny/.arduino15/libraries/SD
Not used: /home/ronny/Arduino/libraries/SD
Using library SPI at version 1.0 in folder: /home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/libraries/SPI
Using library Wire at version 1.0 in folder: /home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/libraries/Wire
Using library SD at version 2.0.0 in folder: /home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/libraries/SD
Using library SDFS at version 0.1.0 in folder: /home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/libraries/SDFS
Using library ESP8266SdFat at version 2.1.1 in folder: /home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/libraries/ESP8266SdFat
Using library LittleFS at version 0.1.0 in folder: /home/ronny/.arduino15/packages/rp2040/hardware/rp2040/3.3.0/libraries/LittleFS
exit status 1

Compilation error: exit status 1

Can you please advice me ?
I’m convinced that SDcard operations can work on RPI2040.
Kind regards,
Ronny


#2

Yes, the Pico can be used with an SDcard - there seems to be a bug in the Philhower core when attempting to write characters. The following diff got it compiling for me:

diff -u ulisp45pico.ino.orig ulisp45pico.ino
--- ulisp45pico.ino.orig	2023-07-18 20:57:04.178757065 -0700
+++ ulisp45pico.ino	2023-07-18 20:56:33.974692992 -0700
@@ -2274,7 +2274,7 @@
 inline void serial1write (char c) { Serial1.write(c); }
 #endif
 #if defined(sdcardsupport)
-inline void SDwrite (char c) { SDpfile.write(c); }
+inline void SDwrite (char c) { SDpfile.write(uint8_t(c)); }
 #endif
 #if defined(ULISP_WIFI)
 inline void WiFiwrite (char c) { client.write(c); }

I have a hacked version of uLisp 4.5 that can read and write files on an SDcard. However, I am using SPI1 and am using an old card reader that needs a slower bus speed to work correctly, so there are a few more changes. If you like, I can post a complete diff.


#3

Hi jimburgs,
Thanks for the reply. I would like to see your complete code yes.
Kind regards,
Ronny


#4

Hi Jimburgs ,

What pin do you use for CS for the sdcard ? I’m using gpio16 , but it’s not working.
I changed this code in the beginning :
#elif defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_QTPY_RP2040) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || defined(ARDUINO_SEEED_XIAO_RP2040)
#define WORKSPACESIZE (22912-SDSIZE) /* Objects (8*bytes) /
#define LITTLEFS
#include <LittleFS.h>
#define FILE_WRITE_BEGIN “w”
#define FILE_READ “r”
#define SDCARD_SS_PIN 16
#define CODESIZE 256 /
Bytes */
#define STACKDIFF 320
#define CPU_RP2040
#if defined(gfxsupport)


#5

Hi Jimburgs ,

your change on line 2274 seems ok , and I got it working now !
I used faulty pins for the spi. This because I used my sparkfun rp2040 thing plus , which mislead me to wrong pins. Using the raspberri pi pico it seems one has to use gp16, gp17 , gp 18 and gp19 for spi0 usage.
So it seems that the only thing that has to be changed is line 2274 (because of a flaw in the arduino code as you state , but this I can not confirm myself)

To David ,
Maybe interesting to know ?

Regards,
Ronny


#6

I almost forgot : you also have to define the SDCARD_SS_PIN to 17 under the rp2040 chip code

#elif defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_QTPY_RP2040) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || defined(ARDUINO_SEEED_XIAO_RP2040)
#define WORKSPACESIZE (22912-SDSIZE) /* Objects (8*bytes) /
#define LITTLEFS
#include <LittleFS.h>
#define FILE_WRITE_BEGIN “w”
#define FILE_READ “r”
#define SDCARD_SS_PIN 17
#define CODESIZE 256 /
Bytes */
#define STACKDIFF 320
#define CPU_RP2040


#7

Thanks - could you summarise all the changes needed? I don’t follow the reference to line 2274.


#8

In case it helps, here is the diff that works for me:

--- ulisp45pico.ino.orig	2023-07-18 20:57:04.178757065 -0700
+++ ulisp45pico.ino	2023-07-19 13:46:22.774774563 -0700
@@ -12,7 +12,7 @@
 // #define resetautorun
 #define printfreespace
 // #define printgcs
-// #define sdcardsupport
+#define sdcardsupport
 // #define gfxsupport
 // #define lisplibrary
 #define assemblerlist
@@ -29,6 +29,9 @@
 #include <limits.h>
 
 #if defined(sdcardsupport)
+#if defined(ARDUINO_RASPBERRY_PI_PICO)
+  #include <SDFS.h>
+#endif
 #include <SD.h>
 #define SDSIZE 91
 #else
@@ -197,10 +200,14 @@
 
 #elif defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_QTPY_RP2040) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || defined(ARDUINO_SEEED_XIAO_RP2040)
   #define WORKSPACESIZE (22912-SDSIZE)    /* Objects (8*bytes) */
-  #define LITTLEFS
-  #include <LittleFS.h>
-  #define FILE_WRITE_BEGIN "w"
-  #define FILE_READ "r"
+  #if defined(sdcardsupport)
+    #define SDCARD_SS_PIN 13
+  #else
+    #define LITTLEFS
+    #include <LittleFS.h>
+    #define FILE_WRITE_BEGIN "w"
+    #define FILE_READ "r"
+  #endif
   #define CODESIZE 256                    /* Bytes */
   #define STACKDIFF 320
   #define CPU_RP2040
@@ -946,7 +953,11 @@
 int saveimage (object *arg) {
 #if defined(sdcardsupport)
   unsigned int imagesize = compactimage(&arg);
+#if defined(ARDUINO_RASPBERRY_PI_PICO)
+  SD.begin(SDCARD_SS_PIN, (uint32_t) SPI_HALF_SPEED, SPI1);
+#else
   SD.begin(SDCARD_SS_PIN);
+#endif
   File file;
   if (stringp(arg)) {
     char buffer[BUFFERSIZE];
@@ -969,7 +980,7 @@
   }
   file.close();
   return imagesize;
-#elif defined(LITTLEFS)
+#elif defined(LITTLEFS) && !defined(sdcardsupport)
   unsigned int imagesize = compactimage(&arg);
   LittleFS.begin(LITTLEFS);
   File file;
@@ -1028,7 +1039,11 @@
 
 int loadimage (object *arg) {
 #if defined(sdcardsupport)
+  #if defined(ARDUINO_RASPBERRY_PI_PICO)
+  SD.begin(SDCARD_SS_PIN, (uint32_t) SPI_HALF_SPEED, SPI1);
+  #else
   SD.begin(SDCARD_SS_PIN);
+  #endif
   File file;
   if (stringp(arg)) {
     char buffer[BUFFERSIZE];
@@ -1109,7 +1124,11 @@
 
 void autorunimage () {
 #if defined(sdcardsupport)
+  #if defined(ARDUINO_RASPBERRY_PI_PICO)
+  SD.begin(SDCARD_SS_PIN, (uint32_t) SPI_HALF_SPEED, SPI1);
+  #else
   SD.begin(SDCARD_SS_PIN);
+  #endif
   File file = SD.open("/ULISP.IMG");
   if (!file) error2(PSTR("problem autorunning from SD card"));
   object *autorun = (object *)SDRead32(file);
@@ -2274,7 +2293,7 @@
 inline void serial1write (char c) { Serial1.write(c); }
 #endif
 #if defined(sdcardsupport)
-inline void SDwrite (char c) { SDpfile.write(c); }
+inline void SDwrite (char c) { SDpfile.write(uint8_t(c)); }
 #endif
 #if defined(ULISP_WIFI)
 inline void WiFiwrite (char c) { client.write(c); }
@@ -3136,7 +3155,11 @@
   Context = temp;
   if (!stringp(filename)) error(PSTR("filename is not a string"), filename);
   params = cdr(params);
+  #if defined(ARDUINO_RASPBERRY_PI_PICO)
+  SD.begin(SDCARD_SS_PIN, (uint32_t) SPI_HALF_SPEED, SPI1);
+  #else
   SD.begin(SDCARD_SS_PIN);
+  #endif
   int mode = 0;
   if (params != NULL && first(params) != NULL) mode = checkinteger(first(params));
   int oflag = O_READ;

#9

When I try to apply that patch I get:

patch unexpectedly ends in middle of line

What version of uLisp does it apply to?

By the way, instead of indenting each line of a listing by 4 spaces you can enclose it with:

````text
listing
````

(four backquotes).


#10

OK, I tried again after adding a return at the end of the diff file, and it ran without errors. Ignore previous comment.


#11

Hi David ,

I’ve used v4.5 for arm (the latest)

This evening I will email you the changes as you requested.

Regards,

Ronny


#12

Hi David ,

As promised the changes I made (and thanks again to Jim )

  • uncommenting line 15

  • between line 203 & 204 added

#define SDCARD_SS_PIN 17

    - on line 2278 (after adding above)

changed line to

inline void SDwrite (char c) { SDpfile.write(uint8_t©); }

Hardware :

gpio16 to MISO sdcard

gpio17 to CS sdcard

gpio18 to sck sdcard

gpio19 to MOSI sdcard

gnd to gnd sdcard

3v3out to 3v3 sdcard

Hope you find this useful !

Kind regards,

Ronny

BTW I’m also testing ulisp on the sparkfun thing plus rp2040 C

Keep you posted about this if you like.

It’s a nice board :-)


#13

I’m tempted by the Challenger RP2040 SD/RTC board from iLabs, which is a Feather-format board with an SD card socket and a real-time clock:

It seems pretty reasonably priced too:

Challenger RP2040 SD/RTC


#14

Hi David ,
Thanks for letting me know.
Looks like an even better board than sparkfun , because of the rtc .
The rtc can even be equipped with a coin cell if you solder it to the board somehow.
And it also has 8Mb of flash (sparkfun has 16Mb … but no rtc)
I’m also interested , let me know if you buy it , I will do the same.
There’s a distributor here in the netherlands :-)

Ronny
R


#15

Starting from a fresh install of Arduino IDE 2 , and uLisp 4.5a I can’t get the SD card to work on a Raspberry Pico or Pico W. The error I get is

15444> (with-sd-card (str "Greeting.txt" 2)  (print "Hello" str))
Error: 'with-sd-card' problem writing to SD card or invalid filename

I’d be grateful for pointers on how most effectively to trace down what is wrong.

The following is what I changed from uLisp 4.5a

15c15
< // #define sdcardsupport
---
> #define sdcardsupport
21c21
< // #define extensions
---
> //#define extensions
31a32,34
> #if defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
>   #include <SDFS.h>
> #endif
200,203c203,210
<   #define LITTLEFS
<   #include <LittleFS.h>
<   #define FILE_WRITE_BEGIN "w"
<   #define FILE_READ "r"
---
>   #if defined(sdcardsupport)
>     #define SDCARD_SS_PIN 13
>   #else
>     #define LITTLEFS
>     #include <LittleFS.h>
>     #define FILE_WRITE_BEGIN "w"
>     #define FILE_READ "r"
>   #endif
218,223c225,235
<   #define LITTLEFS
<   #include <WiFi.h>
<   #include <LittleFS.h>
<   #define FILE_WRITE_BEGIN "w"
<   #define FILE_READ "r"
<   #define CODESIZE 256                    /* Bytes */
---
>   #if defined(sdcardsupport)
>     #define SDCARD_SS_PIN 13
>   #else
>     #define LITTLEFS
>     #include <LittleFS.h>
>     #define FILE_WRITE_BEGIN "w"
>     #define FILE_READ "r"
>   #endif
>    #include <WiFi.h>
> 
> #define CODESIZE 256                    /* Bytes */
948a961,963
> #if defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
>   SD.begin(SDCARD_SS_PIN, (uint32_t) SPI_HALF_SPEED, SPI1);
> #else
949a965
> #endif
972c988
< #elif defined(LITTLEFS)
---
> #elif defined(LITTLEFS) && !defined(sdcardsupport)
1030a1047,1049
>   #if defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
>   SD.begin(SDCARD_SS_PIN, (uint32_t) SPI_HALF_SPEED, SPI1);
>   #else
1031a1051
>   #endif
1111a1132,1134
>   #if defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
>   SD.begin(SDCARD_SS_PIN, (uint32_t) SPI_HALF_SPEED, SPI1);
>   #else
1112a1136
>   #endif
2277c2301
< inline void SDwrite (char c) { SDpfile.write(c); }
---
> inline void SDwrite (char c) { SDpfile.write(uint8_t(c)); }
3138a3163,3165
>   #if defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
>   SD.begin(SDCARD_SS_PIN, (uint32_t) SPI_HALF_SPEED, SPI1);
>   #else
3139a3167
>   #endif
7492c7520
< }
\ No newline at end of file
---
> }

#17

I had power connected to 5v. Changing to 3.3v fixed it, with just the settings indicated by @manes6969