SD class destructor

Is there any class destructor for SD library?

I have a custom board with 3 MCU and one SD card slot to be shared among them. On the first SD card usage for each one of the MCU, SD.begin() is called. What I am looking is a method that "closes" SD class and let me use SD.begin() again because I am experiencing problems sharing the SD card...

Thank you!

There is no easy way to achieve that, the sharing of one resource among multiple MCUs is tending to be a complex thing.

In the case of the SD card it seems to be easier as you don't have background communication with interrupts and the like.
So you must rewrite your code to use SD.begin() just before you're going to access the SD card. You must have some kink of locking between the different MCUs so that only one uses the SD card at a time. When you're finished with SD card put all all used lines to inputs to ensure no level is applied that could result in a short circuit:

pinMode(SPI_MISO_PIN, INPUT);
pinMode(SPI_MOSI_PIN, INPUT);
pinMode(SPI_SCK_PIN, INPUT);
pinMode(4, INPUT);

where you might have to change the 4 to the chip select pin you used for your board.

After that you have to unlock the SD card again the reverse way you have locked it before (with whatever system you have in place there).

Many thanks for your reply.

One of the three MCU (MCU#3) is responsible for create the "path" from the MCU that wants to use SD card and the SD card. Basically it reacts with two interruption routines (one per MCU who can use the SD card (MCU#1 and MCU#2)). After that I close the file.

Accessing SD with only one MCU works fine (using MCU#3 for "path" creation). I can read/open/write and reopen files.

My issue is:

I write a file using MCU#1 and MCU#2 manages to read it. But, when I try to write the fail again using MCU#1 the file cannot be open! I followed your instructions but the problem maintains...

Do I understand you correctly: You're using the SD card to transfer data between different MCUs? If you do so, please post the whole code you're using. This needs checks for several race conditions.

Is this the only way you have to transfer the data?

Yes, you understood correctly. Unfortunately I can't communicate in a different way. Tried NewSoftSerial but had lots of problems.

This is the code running in MCU#1 (ATMEGA 2560)

#include <SD.h>

bool firstSDaccessCall = true;
uint8_t ii = 0;
void setup()
{
  #define PD4 74
  #define PE2 73
  #define PL3 46
  #define PD5 75
  #define MAINSDCS 70
  #define PD3 18
  
  pinMode(PD3,INPUT);
  pinMode(PD4,OUTPUT);
  pinMode(PE2,OUTPUT);
  pinMode(PL3,OUTPUT);
  pinMode(PD5,OUTPUT);
  pinMode(MAINSDCS,OUTPUT);
  Serial.begin(9600);
  delay(2000);
}

void requestSDaccess()
{
  delay(10);
  digitalWrite(PL3,LOW); //this calls MCU#3 routine to create the "path" to the SD card
  digitalWrite(PL3,HIGH);
  
  digitalWrite(PD5,HIGH); //this warns MCU#2 that MCU#1 is using the card
  
  if(firstSDaccessCall)
  {
    Serial.println(SD.begin(MAINSDCS),DEC);
    
    firstSDaccessCall = false;
  }
}

void loop()
{
  Serial.println(millis()/1000);
  
  if((millis()/1000) % 20 == 0)
  {
    while(digitalRead(PD3) == HIGH); //checks if MCU#2 is using SD card
    requestSDaccess(); //ask access to the card
    Serial.print("opening file...");
    File submit = SD.open("submit.txt",FILE_WRITE);
    
    if(submit == NULL)
      Serial.println("NULL!");
    
    submit.print("sub ");
    submit.println(ii,DEC);
    ii++;

    submit.close();
    
//    pinMode(50, OUTPUT); //miso
//    pinMode(51, INPUT); //mosi
//    pinMode(52, INPUT); //sck
//    pinMode(MAINSDCS, INPUT); //ss
    
    digitalWrite(PD5,LOW);
    firstSDaccessCall = true; // this forces the routine to call SD.begin() again (I receive an error with this call)...
    
    digitalWrite(PD4,LOW); //this activates an interruption on MCU#2 so it know that has something to read
    digitalWrite(PD4,HIGH);
    delay(1000);
  }
}

MCU#2 (ATMEGA328P has the following code)

#include <SD.h>
#include <PinChangeInt.h>

bool firstSDaccessCall = true;
bool harvestSubmissionFlag = false;

void PC5handler()
{
  SubmissionFlag = true;
}

void setup()
{
  #define SSPIN 10
  #define PD2 2
  #define PD3 3
  #define PC4 18
  #define PC5 19
  #define PD5 5
  #define PD6 6
  
  pinMode(SSPIN,OUTPUT);
  
  pinMode(PD2,OUTPUT);
  pinMode(PD3,OUTPUT);
  pinMode(PC4,INPUT);
  pinMode(PC5,INPUT);
  pinMode(PD5,OUTPUT);
  pinMode(PD6,INPUT);
  
  digitalWrite(PD2,LOW);
  digitalWrite(PD3,LOW);
  digitalWrite(PD5,LOW);

  PCintPort::attachInterrupt(PC5, PC5handler,RISING);
  
  Serial.begin(9600);
}

void requestSDaccess()
{
  delay(10);
  digitalWrite(PD5,LOW);
  digitalWrite(PD5,HIGH);
  
  digitalWrite(PD2,HIGH);
  
  if(firstSDaccessCall)
  {
    while(!SD.begin(SSPIN));
    
    firstSDaccessCall = false;
  }
}

void readFile()
{
  Serial.println("=================");
  Serial.println("readFile()");
  Serial.println("=================");
  
  File testfile;
  
  char ch;
  
  while(digitalRead(PC4) == HIGH);
  
  requestSDaccess();
  
  testfile = SD.open("submit.txt",FILE_READ);

  while(testfile.available())
  {
    ch = testfile.read();
    
    Serial.print(ch);
  }
  Serial.println();
  
  testfile.close();
  
//  pinMode(12, OUTPUT); //miso
//  pinMode(11, INPUT); //mosi
//  pinMode(13, INPUT); //sck
//  pinMode(SSPIN, INPUT); //ss
  
  digitalWrite(PD2,LOW);
  
//  delay(10000);
}

void loop()
{
  Serial.println(SubmissionFlag,DEC);
  if(SubmissionFlag)
  {
    readFile();
    
    SubmissionFlag = false;
  }
}

and, finally MCU#3 (ATMEGA328P) runs this code:

#include <PinChangeInt.h>

//#define PC0 14
#define PC1 15
#define PC3 17
//#define PC4 18

void setup()
{
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
//  pinMode(PC0,OUTPUT);
  pinMode(PC1,INPUT);
  pinMode(PC3,INPUT);
//  pinMode(PC4,OUTPUT);
  
  PCintPort::attachInterrupt(PC3, SDaccessMCU1,RISING);
  PCintPort::attachInterrupt(PC1, SDaccessMCU2,RISING);
}

void SDaccessMCU1()
{
  digitalWrite(7,LOW);
  digitalWrite(8,HIGH);
  digitalWrite(9,LOW);
}

void SDaccessMCU2()
{
  digitalWrite(7,HIGH);
  digitalWrite(8,LOW);
  digitalWrite(9,LOW);
}

void loop()
{
}

Why is this line in both first MCUs?

//    pinMode(50, OUTPUT); //miso

This should be

    pinMode(50, INPUT); //miso

... and not commented out. They are all set as inputs because this way they don't disturb the other MCU. Otherwise, let's say MCU1 has set MISO as OUTPUT as well as MCU2 but MCU1 has the pin LOW, MCU2 has it HIGH. This is a classical short circuit frying your Arduino's port.

Additionally to understand what's going on I think you should post a drawing of the circuitry. Do you switch the SPI lines with some multiplexing hardware? Or are all SPI lines connected together?

Thanks for all replies.

I solved my problem. I had a race condition...