ST Nucleo F401RE + SDFileSystem Library + SparkFun MicroSD Breakout Board - problem

19 Aug 2014

I'm try using ST Nucleo F401RE + SDFileSystem Library + SparkFun MicroSD Breakout Board. Everything works, but through 2-5 times of reading or writing everything hangs.

/* 

SparkFun MicroSD Breakout Board
MicroSD Breakout    mbed
   CS  o-------------o 8    (DigitalOut cs)
   DI  o-------------o 5    (SPI mosi)
   VCC o-------------o VOUT
   SCK o-------------o 7    (SPI sclk)
   GND o-------------o GND
   DO  o-------------o 6    (SPI miso)
   CD  o

PB_13 = SCK
PB_15 = MOSI
PB_14 = MISO
PB_1  = CS

*/

#include "mbed.h"
#include "TextOLED.h"
#include "SDFileSystem.h"

#define LM75_REG_TEMP (0x00) // Temperature Register
#define LM75_REG_CONF (0x01) // Configuration Register
#define LM75_ADDR     (0x90) // LM75 address A0 A1 A2 - to GND

#define LM75_REG_TEMP (0x00) // Temperature Register
#define LM75_REG_CONF (0x01) // Configuration Register
#define LM75_ADDR     (0x90) // LM75 address A0 A1 A2 - to GND

// MOSI, MISO, SCK, CS

SDFileSystem sd(PB_15,PB_14,PB_13,PB_1,"sd"); // the pinout on the mbed Cool Components workshop board

I2C i2c(I2C_SDA, I2C_SCL);

// DigitalOut myled(LED1);

DigitalIn blue(D2);

Serial pc(SERIAL_TX,SERIAL_RX);

// volatile

char TempCelsiusDisplay[] = "+abc.d C";

TextLCD lcd(D13,D12,D11,D10,D9,D8); // rs, e, d4-d7

char buffer[32];
char c[32];
char Buff[256];
FILE *fp;

Timer t,w;

time_t seconds;

int main()
{

    pc.baud(9600);

    set_time(1387188323); // Set RTC time to 16 December 2013 10:05:23 UTC

    pc.baud(9600);

    lcd.cls();

    char data_write[2];
    char data_read[2];

    /*
    - Configure the Temperature sensor device STLM75:
    - Thermostat mode Interrupt
    - Fault tolerance: 0
    */

    data_write[0] = LM75_REG_CONF;
    data_write[1] = 0x02;

    int status = i2c.write(LM75_ADDR, data_write, 2, 0);

    if (status != 0) {
        while (1) {
            lcd.cls();
            lcd.printf("Error LM75");
        }
    }

    t.start();
    w.start();

    while (1) {

        seconds = time(NULL);

        // Read temperature register

        data_write[0] = LM75_REG_TEMP;
        i2c.write(LM75_ADDR, data_write, 1, 1); // no stop
        i2c.read(LM75_ADDR, data_read, 2, 0);

        // Calculate temperature value in Celcius

        int tempval = (int)((int)data_read[0] << 8) | data_read[1];
        tempval >>= 7;
        if (tempval <= 256) {
            TempCelsiusDisplay[0] = '+';
        } else {
            TempCelsiusDisplay[0] = '-';
            tempval = 512 - tempval;
        }

        // Decimal part (0.5°C precision)
        if (tempval & 0x01) {
            TempCelsiusDisplay[5] = 0x05 + 0x30;
        } else {
            TempCelsiusDisplay[5] = 0x00 + 0x30;
        }

        // Integer part

        tempval >>= 1;
        TempCelsiusDisplay[1] = (tempval / 100) + 0x30;
        TempCelsiusDisplay[2] = ((tempval % 100) / 10) + 0x30;
        TempCelsiusDisplay[3] = ((tempval % 100) % 10) + 0x30;

        // Display result

        if(pc.readable()) {
            char c = pc.getc();
            if (c == 'c') {
                pc.printf("\r\ntemp = %s\r\n", TempCelsiusDisplay);
            }

            if (c == 'w') {
                fp = fopen("/sd/temp.txt","a");

                if(fp == NULL) {
                    pc.printf("Could not open file for WRITE\r\n");
                } else {
                    pc.printf("\r\nAll is OK (WRITE)\r\n");
                    strftime(buffer, 32, "%H:%M:%S", localtime(&seconds));
                    fprintf(fp,"Time: %s ", buffer);
                    fprintf(fp,"Temp = %s\r\n", TempCelsiusDisplay);
                    fclose(fp);
                }
            }

            if (c == 'f') {
                fp = fopen("/sd/temp.txt","r");

                if(fp == NULL) {
                    pc.printf("Could not open file for READ\r\n");
                } else {
                    pc.printf("\r\nAll is OK (READ)\r\n");

                    while(fgets (Buff, 256, fp) != NULL) {
                        Buff[strlen(Buff)-1] = 0;
                        pc.printf("%s\r\n", Buff);
                    }

                }

                fclose(fp);

            }
        }



        if (t.read() > 1) {
            pc.printf("Write...LCD ->");
            lcd.cls();
            lcd.locate(0,1);
            lcd.printf(TempCelsiusDisplay);
            lcd.locate(0,0);
            strftime(buffer, 32, "%H:%M:%S\n", localtime(&seconds));
            lcd.printf("Time: %s", buffer);
            if(blue) {
                lcd.locate(11,1);
                lcd.printf("CON ");
            } else {
                lcd.locate(11,1);
                lcd.printf("None");
            }
            t.stop();
            t.reset();
            t.start();
            pc.printf("LCD...DONE\r\n");
        }


        if (w.read() > 100) {
            pc.printf("Write...SD ->");
            fp = fopen("/sd/temp.txt","a");
            strftime(buffer, 32, "%H:%M:%S", localtime(&seconds));
            fprintf(fp,"Time: %s ", buffer);
            fprintf(fp,"Temp = %s\r\n", TempCelsiusDisplay);
            fclose(fp); 
            w.stop();
            w.reset();
            w.start();
            pc.printf("Write...DONE\r\n");
        }

    }
}
19 Aug 2014

This is likely your problem, it has to do with how stdio is implemented on microlib. If I may make a suggestion however, the official SDFileSystem leaves much to be desired. I've written (am writing) an alternative that's faster and more reliable, more details here. You should also be aware of the performance issues associated with using the stdio API for file access.

20 Aug 2014

Thank you very much.