Modifying the SD Library, doesn't compile.

Hi.

I’m trying to use an SD Card in my project, which can be inserted or ejected at will by the user. The Arduino SD Library, as it stands, cannot do this as once as begin() has been successfully called, you cannot re-begin without resetting.

I’ve read that using the underlying SDFat library directly is a much better choice and allows this functionality, but I couldn’t get that to compile when installed as per the instructions found in the readme file (see: GitHub - greiman/SdFat: Arduino FAT16/FAT32 exFAT Library) - complains about being unable to find various files contained in subdirectories. I tried moving files about to satisfy the errors, creating more. I decided I probably didn’t know enough about the structure of the library to muck about with it any further.

Next, I read about a single-line quick fix which can be made the Arduino SD Library, which means that begin() will close an open SD Card session if there is one, before attempting to open the new one (see: https://forum.arduino.cc/index.php?topic=46969.0). This suits me fine, and works if I modify the SD Library within the Arduino/ installation folder. However, I prefer not to modify the root libraries directly as they may get overwritten by future updates and it creates a hidden dependency. Instead I prefer to make a local copy within the sketch.

I’ve done this by copying the contents of libraries/SD/src to a folder within my sketch called SDC/, making the single line modifiction to begin(), and including this new library within my program (see source at end). I also needed to modify the #includes in SD.h from <> to “” to allow it to find the utility/ libraries. After these changes, however, it fails to link with the errors shown further below.

My ultimate question then is: Can someone please help me either get SDFat to work within Arduino IDE, or allow me to compile my copied-and-modified version of SD?

Sketch Source:

#include <SPI.h>
#include <LiquidCrystal.h>
#include "SDC/SD.h"
#include "const.hpp"
#include "debug.hpp"
#include "hd44780_lcd.hpp"

Hd44780_Lcd lcd(PIN_LCD_RS, PIN_LCD_E, PIN_LCD_D4, PIN_LCD_D5, PIN_LCD_D6, PIN_LCD_D7, LCD_COLS, LCD_ROWS);
volatile boolean cardInserted = false;
volatile boolean cardReadOnly = false;
volatile boolean cardOpened = false;

void setup()
{
  //Start debugging
  STARTDEBUG;

  //Show splash screen.
  lcd.print(L_FIRMWARE_TITLE, 0, 0);
  lcd.print(FIRMWARE_VERSION);
  lcd.print(L_FIRMWARE_AUTHOR, 0, 1);
  delay(1000); //For a minimum of a second.

  lcd.clear();
  lcd.print(L_STARTING_UP, 0, 0);

  // [...] There's a bunch of pinMode()s here I've removed as they're not relevant

  pinMode(PIN_SDC_WP, INPUT_PULLUP);
  pinMode(PIN_SDC_CD, INPUT_PULLUP);

  SPI.begin();

  attachInterrupt(digitalPinToInterrupt(PIN_SDC_CD), &ISR_SdcInserted, CHANGE);
  attachInterrupt(digitalPinToInterrupt(PIN_SDC_WP), &ISR_SdcInserted, CHANGE);

  lcd.clear();
  lcd.print("Card:     ", 0, 0);
  lcd.print("Writable: ", 0, 1);

  ISR_SdcInserted();

  //if (digitalRead(PIN_SDC_WP)

  //Setup the SD Card reader.
  //SD.begin(PIN_SDC_CS);
}

void loop()
{
  if (cardInserted)
  {
    lcd.print((char)2, 10, 0);
  } else {
    lcd.print((char)3, 10, 0);
  }
  
  if (!cardReadOnly)
  {
    lcd.print((char)2, 10, 1);
  } else {
    lcd.print((char)3, 10, 1);
  }

  if (cardInserted && !cardOpened)
  {
    cardOpened = SD.begin(PIN_SDC_CS);
  }
  
  if (cardOpened)
  {
    lcd.print((char)2, 12, 0);
  } else {
    lcd.print((char)3, 12, 0);
  }
  
}

void ISR_SdcInserted()
{
  cardInserted = sdcPresent();
  cardReadOnly = sdcReadOnly();
  if (!cardInserted) {
    cardOpened = false;
  }
}

inline boolean sdcPresent()
{
  return !digitalRead(PIN_SDC_CD);
}

inline boolean sdcReadOnly()
{
  return digitalRead(PIN_SDC_WP);
}

Error:

Arduino: 1.8.1 (Windows 7), Board: "Arduino Due (Programming Port)"

sketch\firmware.ino.cpp.o: In function `loop':

D:\Projects\EL600\FPGA-6502\ROM Programmer Firmware\firmware/firmware.ino:136: undefined reference to `SDLib::SDClass::begin(unsigned char)'

D:\Projects\EL600\FPGA-6502\ROM Programmer Firmware\firmware/firmware.ino:136: undefined reference to `SDLib::SD'

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board Arduino Due (Programming Port).

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
#include "SDC/SD.h"

What is this? Either the SD.h and other files are in the sketch directory, or they aren’t. If they are, this include statement is wrong. If they aren’t, then the symbols ("" instead of <>) are wrong.

They're in the sketch folder, within a subfolder called SDC: I don't think that line is wrong, but hey there might be something I'm missing.

They're in the sketch folder, within a subfolder called SDC

In the libraries folder, the only sub-folders allowed are called examples and src.

In the sketch folder, NO subdirectories are allowed.

OK. I moved out the SD files from the subdirectory, (and also moved out the files from the utility subsubdirectory) so its now completely flat. I also adjusted SD.h a little further, as it had two #includes pointing to the now non-existant utilities directory.

Now I get the errors in the attachments, which are too large to put in the body of the post.

Basically, its saying that all the SD stuff is being declared twice, which is bizarre because I’m only asking for my own version of the library, not both.

errors2.txt (29.7 KB)

and also moved out the files from the utility subsubdirectory) so its now completely flat. I also adjusted SD.h a little further, as it had two #includes pointing to the now non-existant utilities directory.

The utility subdirectory was allowed. Sorry if I gave the wrong impression that it wasn't.

It looks to me like you have a copy of the SdFat library in the sketch folder AND in the (core?) libraries folder.

D:\Program Files\Arduino\libraries\SD

contains a copy, and your sketch folder contains a copy.

Yes, there are two copies of the SD library lying abount - one in the Arduino installation folder at "D:\Program Files\Arduino\libraries\SD", the other is now in the root of the Sketch's folder.

As I stated in the OP, one of the points here is to not modify the installation folder at all if possible, as that creates hidden dependencies. I don't see why the copy in the installation folder should cause a problem; I'm not asking it to use that one.

Yes, there are two copies of the SD library lying abount

When you accept that you can't do that, you'll be able to make progress.

I’ve come up with a completely different solution which works, requires no changes to any libraries, and is actually better suited to my application. I’m just doing a software reset when I detect the SD card has been removed, using the following function:

void softwareReset()
{
  RSTC->RSTC_CR = 0xA5000005; 
  while(true);
}

Having said that, I am very puzzled by the compiler thinking there were two libraries. As far as I’m aware,

#include "SD.h" // Include a file called SD.h from the Sketch folder
#include <SD.h> // Include a file called SD.h from the libraries folder

So I don’t understand why using the former implicitly does the latter, this seems very counter-intuitive and unhelpful behaviour to me, and the root of the most problem I was having trying to make a modified copy of the library.

So I don't understand why using the former implicitly does the latter

Enable verbose mode when compiling. Copy all the output to a file, so you can study it.

In particular, notice that the IDE has copied your sketch someplace else for compiling.

Navigate to that folder. See just what else the IDE has copied to the same folder.

Perhaps then it will become obvious.