Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2 cannot use with Particle Boron SPI1 #285

Closed
zabaat opened this issue Mar 30, 2021 · 5 comments
Closed

v2 cannot use with Particle Boron SPI1 #285

zabaat opened this issue Mar 30, 2021 · 5 comments

Comments

@zabaat
Copy link

zabaat commented Mar 30, 2021

Hello, we were able to get this working with version 1 of your library, but with v2 we are unable to init. It looks like the ability to call sd(SPI1) is gone now. How to make this work in V2 with particle? Both code are below.

#define IMPLEMENT_SPI_PORT_SELECTION 1
// Quick hardware test for SPI card access.
//
// clang-format off
#include <SPI.h>


#include "Particle.h"
#include "SdFat.h"
#include "sdios.h"

// clang-format on
//
// Set DISABLE_CHIP_SELECT to disable a second SPI device.
// For example, with the Ethernet shield, set DISABLE_CHIP_SELECT
// to 10 to disable the Ethernet controller.
SYSTEM_MODE(MANUAL);
SYSTEM_THREAD(ENABLED);
const int8_t DISABLE_CHIP_SELECT = -1;
//
// Test with reduced SPI speed for breadboards.  SD_SCK_MHZ(4) will select
// the highest speed supported by the board that is not over 4 MHz.
// Change SPI_SPEED to SD_SCK_MHZ(50) for best performance.
#define SPI_SPEED SD_SCK_MHZ(4)
//------------------------------------------------------------------------------
// File system object.
SdFat sd((SPIClass*)&SPI1);

// Serial streams
ArduinoOutStream cout(Serial);

// input buffer for line
char cinBuf[40];
ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf));

// SD card chip select
int chipSelect;

void cardOrSpeed() {
    cout << F("Try another SD card or reduce the SPI bus speed.\n");
    cout << F("Edit SPI_SPEED in this program to change it.\n");
}

void reformatMsg() {
    cout << F("Try reformatting the card.  For best results use\n");
    cout << F("the SdFormatter program in SdFat/examples or download\n");
    cout << F("and use SDFormatter from www.sdcard.org/downloads.\n");
}

void setup() {
    Cellular.off();
    Serial.begin(9600);

    // Wait for USB Serial
    waitFor(Serial.isConnected, 15000);
    delay(1000);
    cout << F("\nSPI pins:\n");
    cout << F("MISO: ") << int(MISO) << endl;
    cout << F("MOSI: ") << int(MOSI) << endl;
    cout << F("SCK:  ") << int(SCK) << endl;
    cout << F("SS:   ") << int(SS) << endl;
    delay(1000);
    if (DISABLE_CHIP_SELECT < 0) {
        cout << F(
            "\nBe sure to edit DISABLE_CHIP_SELECT if you have\n"
            "a second SPI device.  For example, with the Ethernet\n"
            "shield, DISABLE_CHIP_SELECT should be set to 10\n"
            "to disable the Ethernet controller.\n");
    }
    cout << F(
        "\nSD chip select is the key hardware option.\n"
        "Common values are:\n"
        "Arduino Ethernet shield, pin 4\n"
        "Sparkfun SD shield, pin 8\n"
        "Adafruit SD shields and modules, pin 10\n");
}

void read() {
    File myFile = sd.open("test.txt", FILE_READ);
    // if the file opened okay, write to it:
    if (myFile) {
        // read from the file until there's nothing else in it:
        while (myFile.available()) {
            Serial.write(myFile.read());
        }
        // close the file:
        myFile.close();
    } else {
        cout << F("Error opening test.txt");
    }
}

void write() {
    File myFile = sd.open("test.txt", FILE_WRITE);
    // if the file opened okay, write to it:
    if (myFile) {
        Serial.print("Writing to test.txt...");
        myFile.println("testing 1, 2, 3.");
        // close the file:
        myFile.close();
        Serial.println("done.");
    } else {
        cout << F("Error opening test.txt");
    }
}

void readWriteTest() {
    write();
    read();
}

bool firstTry = true;
void loop() {
    // Read any existing Serial data.
    do {
        delay(10);
    } while (Serial.available() && Serial.read() >= 0);

    if (!firstTry) {
        cout << F("\nRestarting\n");
        delay(10000);
    }
    firstTry = false;
    chipSelect = 5;
    // cout << F("\nEnter the chip select pin number: ");
    // while (!Serial.available()) {
    //     SysCall::yield();
    // }
    // cin.readline();
    // if (cin >> chipSelect) {
    //     cout << chipSelect << endl;
    // } else {
    //     cout << F("\nInvalid pin number\n");
    //     return;
    // }
    if (DISABLE_CHIP_SELECT < 0) {
        cout << F(
            "\nAssuming the SD is the only SPI device.\n"
            "Edit DISABLE_CHIP_SELECT to disable another device.\n");
    } else {
        cout << F("\nDisabling SPI device on pin ");
        cout << int(DISABLE_CHIP_SELECT) << endl;
        pinMode(DISABLE_CHIP_SELECT, OUTPUT);
        digitalWrite(DISABLE_CHIP_SELECT, HIGH);
    }
    if (!sd.begin(chipSelect, SPI_SPEED)) {
        if (sd.card()->errorCode()) {
            cout << F(
                "\nSD initialization failed.\n"
                "Do not reformat the card!\n"
                "Is the card correctly inserted?\n"
                "Is chipSelect set to the correct value?\n"
                "Does another SPI device need to be disabled?\n"
                "Is there a wiring/soldering problem?\n");
            cout << F("\nerrorCode: ") << hex << showbase;
            cout << int(sd.card()->errorCode());
            cout << F(", errorData: ") << int(sd.card()->errorData());
            cout << dec << noshowbase << endl;
            return;
        }
        if (sd.vol()->fatType() == 0) {
            cout << F("Can't find a valid FAT16/FAT32 partition.\n");
            reformatMsg();
            return;
        }
        cout << F("begin failed, can't determine error type\n");
        return;
    }
    cout << F("\nCard successfully initialized.\n");
    cout << endl;
    readWriteTest();
    uint32_t size = sd.card()->cardSize();
    if (size == 0) {
        cout << F("Can't determine the card size.\n");
        cardOrSpeed();
        return;
    }
    uint32_t sizeMB = 0.000512 * size + 0.5;
    cout << F("Card size: ") << sizeMB;
    cout << F(" MB (MB = 1,000,000 bytes)\n");
    cout << endl;
    cout << F("Volume is FAT") << int(sd.vol()->fatType());
    cout << F(", Cluster size (bytes): ") << 512L * sd.vol()->blocksPerCluster();
    cout << endl
         << endl;

    cout << F("Files found (date time size name):\n");
    sd.ls(LS_R | LS_DATE | LS_SIZE);

    if ((sizeMB > 1100 && sd.vol()->blocksPerCluster() < 64) || (sizeMB < 2200 && sd.vol()->fatType() == 32)) {
        cout << F("\nThis card should be reformatted for best performance.\n");
        cout << F("Use a cluster size of 32 KB for cards larger than 1 GB.\n");
        cout << F("Only cards larger than 2 GB should be formatted FAT32.\n");
        reformatMsg();
        return;
    }
    // Read any extra Serial data.
    do {
        delay(10);
    } while (Serial.available() && Serial.read() >= 0);
    cout << F("\nSuccess!  Type any character to restart.\n");
    while (!Serial.available()) {
        SysCall::yield();
    }
}

V2

// Quick hardware test for SPI card access.
//
// clang-format off
#include <SPI.h>
#include "Particle.h"

#define SD_USE_CUSTOM_SPI 1
#define SD_HAS_CUSTOM_SP 1
#define IMPLEMENT_SPI_PORT_SELECTION 1
#include "SdFat.h"
#include "sdios.h"
PRODUCT_ID(14114);   // replace by your product ID
PRODUCT_VERSION(2);  // increment each time you upload to the console

// clang-format on
//
// Set DISABLE_CHIP_SELECT to disable a second SPI device.
// For example, with the Ethernet shield, set DISABLE_CHIP_SELECT
// to 10 to disable the Ethernet controller.
SYSTEM_MODE(MANUAL);
SYSTEM_THREAD(ENABLED);
const int8_t DISABLE_CHIP_SELECT = -1;
//
// Test with reduced SPI speed for breadboards.  SD_SCK_MHZ(4) will select
// the highest speed supported by the board that is not over 4 MHz.
// Change SPI_SPEED to SD_SCK_MHZ(50) for best performance.
#define SPI_SPEED SD_SCK_MHZ(4)
//------------------------------------------------------------------------------
// File system object.
// SPI = &SPI1;
SdFat sd;

// Serial streams
ArduinoOutStream cout(Serial);

// input buffer for line
char cinBuf[40];
ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf));

// SD card chip select
int chipSelect;

void cardOrSpeed() {
    cout << F("Try another SD card or reduce the SPI bus speed.\n");
    cout << F("Edit SPI_SPEED in this program to change it.\n");
}

void reformatMsg() {
    cout << F("Try reformatting the card.  For best results use\n");
    cout << F("the SdFormatter program in SdFat/examples or download\n");
    cout << F("and use SDFormatter from www.sdcard.org/downloads.\n");
}

void read() {
    File myFile = sd.open("test.txt", FILE_READ);
    // if the file opened okay, write to it:
    if (myFile) {
        // read from the file until there's nothing else in it:
        while (myFile.available()) {
            Serial.write(myFile.read());
        }
        // close the file:
        myFile.close();
    } else {
        cout << F("Error opening test.txt");
    }
}

void write() {
    File myFile = sd.open("test.txt", FILE_WRITE);
    // if the file opened okay, write to it:
    if (myFile) {
        Serial.print("Writing to test.txt...");
        myFile.println("testing 1, 2, 3.");
        // close the file:
        myFile.close();
        Serial.println("done.");
    } else {
        cout << F("Error opening test.txt");
    }
}

void readWriteTest() {
    write();
    read();
}

void setup() {
    Cellular.off();
    Serial.begin(9600);

    // Wait for USB Serial
    waitFor(Serial.isConnected, 15000);
    delay(1000);
    cout << F("\nSPI pins:\n");
    cout << F("MISO: ") << int(MISO) << endl;
    cout << F("MOSI: ") << int(MOSI) << endl;
    cout << F("SCK:  ") << int(SCK) << endl;
    cout << F("SS:   ") << int(SS) << endl;

    if (DISABLE_CHIP_SELECT < 0) {
        cout << F(
            "\nBe sure to edit DISABLE_CHIP_SELECT if you have\n"
            "a second SPI device.  For example, with the Ethernet\n"
            "shield, DISABLE_CHIP_SELECT should be set to 10\n"
            "to disable the Ethernet controller.\n");
    }
    cout << F(
        "\nSD chip select is the key hardware option.\n"
        "Common values are:\n"
        "Arduino Ethernet shield, pin 4\n"
        "Sparkfun SD shield, pin 8\n"
        "Adafruit SD shields and modules, pin 10\n");
}

bool firstTry = true;
void loop() {
    // Read any existing Serial data.
    do {
        delay(10);
    } while (Serial.available() && Serial.read() >= 0);

    if (!firstTry) {
        cout << F("\nRestarting\n");
        delay(10000);
    }
    firstTry = false;
    chipSelect = 5;

    if (DISABLE_CHIP_SELECT < 0) {
        cout << F(
            "\nAssuming the SD is the only SPI device.\n"
            "Edit DISABLE_CHIP_SELECT to disable another device.\n");
    } else {
        cout << F("\nDisabling SPI device on pin ");
        cout << int(DISABLE_CHIP_SELECT) << endl;
        pinMode(DISABLE_CHIP_SELECT, OUTPUT);
        digitalWrite(DISABLE_CHIP_SELECT, HIGH);
    }
    if (!sd.begin(chipSelect, SPI_SPEED)) {
        if (sd.card()->errorCode()) {
            cout << F(
                "\nSD initialization failed.\n"
                "Do not reformat the card!\n"
                "Is the card correctly inserted?\n"
                "Is chipSelect set to the correct value?\n"
                "Does another SPI device need to be disabled?\n"
                "Is there a wiring/soldering problem?\n");
            cout << F("\nerrorCode: ") << hex << showbase;
            cout << int(sd.card()->errorCode());
            cout << F(", errorData: ") << int(sd.card()->errorData());
            cout << dec << noshowbase << endl;
            return;
        }
        if (sd.vol()->fatType() == 0) {
            cout << F("Can't find a valid FAT16/FAT32 partition.\n");
            reformatMsg();
            return;
        }
        cout << F("begin failed, can't determine error type\n");
        return;
    }
    cout << F("\nCard successfully initialized.\n");
    cout << endl;
    readWriteTest();

    uint32_t size = sd.card()->cardSize();
    if (size == 0) {
        cout << F("Can't determine the card size.\n");
        cardOrSpeed();
        return;
    }
    uint32_t sizeMB = 0.000512 * size + 0.5;
    cout << F("Card size: ") << sizeMB;
    cout << F(" MB (MB = 1,000,000 bytes)\n");
    cout << endl;
    cout << F("Volume is FAT") << int(sd.vol()->fatType());
    cout << F(", Cluster size (bytes): ") << 512L * sd.vol()->blocksPerCluster();
    cout << endl
         << endl;

    cout << F("Files found (date time size name):\n");
    sd.ls(LS_R | LS_DATE | LS_SIZE);

    if ((sizeMB > 1100 && sd.vol()->blocksPerCluster() < 64) || (sizeMB < 2200 && sd.vol()->fatType() == 32)) {
        cout << F("\nThis card should be reformatted for best performance.\n");
        cout << F("Use a cluster size of 32 KB for cards larger than 1 GB.\n");
        cout << F("Only cards larger than 2 GB should be formatted FAT32.\n");
        reformatMsg();
        return;
    }
    // Read any extra Serial data.
    do {
        delay(10);
    } while (Serial.available() && Serial.read() >= 0);
    cout << F("\nSuccess!  Type any character to restart.\n");
    while (!Serial.available()) {
        SysCall::yield();
    }
}

this outputs
SD initialization failed.
Do not reformat the card!
Is the card correctly inserted?
Is chipSelect set to the correct value?
Does another SPI device need to be disabled?
Is there a wiring/soldering problem?

errorCode: 0x1, errorData: 0xff

@zabaat
Copy link
Author

zabaat commented Mar 30, 2021

Nevermind - found the documentation for multiple spi in the examples. thanks for htis lib!

@zabaat zabaat closed this as completed Mar 30, 2021
@TrikkStar
Copy link

@zabaat Where in the documentation/examples did you find reference for Multiple SPI? I'm in a similar position but not seeing what you found.

@zabaat
Copy link
Author

zabaat commented Apr 20, 2021

@zabaat Where in the documentation/examples did you find reference for Multiple SPI? I'm in a similar position but not seeing what you found.

I think I divined the information from this and possibly a fever dream of desperation.

@zabaat
Copy link
Author

zabaat commented Apr 20, 2021

@TrikkStar here is the relevant code snippets to init.

#define ENABLE_DEDICATED_SPI 1
// clang-format off
#include <SPI.h>
#include "Particle.h"
#include <SdFat.h> // needs init before the publish queue
// #include <SdCardLogHandlerRK.h>
#include "PublishQueueAsyncRK.h"

#define SPI_SPEED SPI_FULL_SPEED  //SD_SCK_MHZ(18)
// Setup SD card writing settings
#define SD2_CONFIG SdSpiConfig(5, DEDICATED_SPI, SPI_FULL_SPEED, &SPI1)



int initSdCard() {
    if (sdCard.begin(SD2_CONFIG)) {  //if (sdCard.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)) 
....

@greiman
Copy link
Owner

greiman commented Apr 21, 2021

The html documentation in SdFat/doc has the four sd.begin() calls and four SdSpiConfig() constructors. The problem is SdFat now has so many options and classes that it is difficult find what you need in the documentation.

Here are screen shots of begin and SdFatConfig from SdFat/doc/html:

begin

SdSpiConfig

There are now over a hundred boards that can use SdFat so it is impossible to test or give examples for all of these.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants