Arm Mbed OS support forum

Mbed SD filesystem problem opening file

Hi everyone,
I hope you can help me with an issue using filesystem. I haw a custom board with microcontroller LPC1768 and two SD card connect to LPC1768 using the same spi connection but different chip select. When I use the function “initSD” everything works well, I can create files in both SD card and add one line in a file. After that initialization I call function “SaveDataSD” in order to save data in both SDcard, the filesystem is mounted well but when I try to open a file I get a null pointer from “fopen” and I get the next output with printf:

Mount SD Sucess
Error, can’t open or create file datalogger.csv
Unmounting…
Error save SD1
Mount SD Sucess
Error, can’t open or create file datalogger.csv
Unmounting…
Error save SD2

Can someone give me a hint to solve this problem?

SDBlockDevice   sd1(p5, p6, p7, p8, 25000000);
SDBlockDevice   sd2(p5, p6, p7, p29, 25000000);
FATFileSystem   fs("fs");
FILE            *fd;
static  BufferedSerial serial_Data_Exchange(p28, p27);
DigitalIn   cardDetectuSD1(p21);
DigitalIn   cardDetectuSD2(p22);
int     initSD(SDBlockDevice *sdDevice);
void    getDataUART(void);
int     saveDataSD(SDBlockDevice *sdDevice);

int main(void)
{
    while(init() != 0)
    {
        printf("Error Init().\n");
        serial_Data_Exchange.write("Error Init\n", strlen("Error Init\n"));
        ThisThread::sleep_for(DELAY_INIT_UART);
    }
    serial_Data_Exchange.write("Init OK\n", strlen("Init OK\n"));
    uartBuffer_thread.start(callback(getDataUART));
    while (1) 
    {
    }
}
void getDataUART()
{
    while(true) 
    {
        ThisThread::sleep_for(1s);
        if (saveDataSD(&sd1) != 0)
        { 
            serial_Data_Exchange.write("Error save SD1\n", strlen("Error save SD1\n"));
            printf("Error save SD1\n");
        }
        else 
        {
            serial_Data_Exchange.write("ACK save JSON SD1\n", strlen("ACK save JSON SD1\n"));
            printf("ACK save JSON SD1\n");
        }
    }
}
int initSD(SDBlockDevice *sdDevice)
{

    int error = fs.mount(sdDevice);
    if (error != 0)
    {
        printf("Mount SD failed, error = %d.\r\n", error);
        return error;
    }
    else 
        printf("Mount SD Sucess\r\n");
    fd = fopen("/fs/datalogger.csv", "r");
    if(fd == NULL)
    {
        printf("File datalogger.csv not exists, creating file\r\n");
        fd = fopen("/fs/datalogger.csv", "a");
        if(fd == NULL)
        {
            printf("Can´t create file datalogger.csv\r\n");
            printf("Unmounting...\r\n");
            error = fs.unmount();
            if(error != 0)
            {
                printf("Unmount Failed error = %d...\r\n", error);
                return -error;
            }
            return -EPERM;
        }
        printf("File datalogger.csv created\r\n");
        printf("Adding first line\r\n");
        fwrite(firstLine, sizeof(char), sizeof(firstLine), fd);
        printf("Closing File\r\n");
        fclose(fd);
    }
    else
    {
        printf("File datalogger.csv Exists\r\n");
        printf("Closing File\r\n");
        fclose(fd);
    }
    fd = fopen("/fs/log.json", "r");
    if(fd == NULL)
    {
        printf("File log.json not exists, creating file\r\n");
        fd = fopen("/fs/log.json", "a");
        if(fd == NULL)
        {
            printf("Can´t create file log.json\r\n");
            printf("Unmounting...\r\n");
            error = fs.unmount();
            if(error != 0)
            {
                printf("Unmount Failed error = %d...\r\n", error);
                return -error;
            }
            return -EPERM;
        }
        printf("File log.json created\r\n");
        printf("Closing File\r\n");
        fclose(fd);
        printf("Unmounting...\r\n");
        error = fs.unmount();
        if(error != 0)
        {
            printf("Unmount Failed error = %d...\r\n", error);
            return -error;
        }
        return 0;
    }
    else
    {
        printf("File log.json Exists\r\n");
        printf("Closing File\r\n");
        fclose(fd);
    }
    printf("Unmounting...\r\n");
    error = fs.unmount();
    if(error != 0)
    {
        printf("Unmount Failed error = %d...\r\n", error);
        return -error;
    }
    fd = NULL;
    return 0;
}

int saveDataSD(SDBlockDevice *sdDevice)
{
    int error = fs.mount(sdDevice);
    if (error != 0)
    {
        printf("Mount SD failed, error = %d.\r\n", error);
        return error;
    }
    else {
        printf("Mount SD Sucess\r\n");
    }
    fd = fopen("datalogger.csv", "a");
    if(fd == NULL)
    {
        printf("Error, can't open or create file datalogger.csv\r\n");
        printf("Unmounting...\r\n");
        fs.unmount();
        return -ENOENT;
    }
    else {
        printf("File datalogger.csv open\r\n");
        fwrite(dataLog, sizeof(char), strlen(dataLog), fd);
        printf("Closing file.\r\n");
        fclose(fd);
    }
    fd = fopen("/fs/log.json", "a");
    if(fd == NULL)
    {
        printf("Error, can't open or create file log.json\r\n");
        printf("Unmounting...\r\n");
        fs.unmount();
        return -ENOENT;
    }
    else {
        printf("File log.json open\r\n");
        fwrite(buf, sizeof(char), strlen(buf), fd);
        fwrite("\n", sizeof(char), 1, fd);
        printf("Closing file.\r\n");
        fclose(fd);
        printf("Unmounting...\r\n");
        fs.unmount();
    }
    return 0;
}

Hello,

usually is good to make the affected code simple as can for easy reproduce the issue.

  • You wrote about a console output and two SD cards but the published code uses only object sd1.
  • An init() function, called in the while loop, is not declared/visible.
  • On the other hand, initSD(sdbd) function is not used anywhere.

In the function saveDataSD you have this line

fd = fopen("datalogger.csv", "a");

but it seems like there missing /fs/

fd = fopen("/fs/datalogger.csv", "a");

for avoid this is good to use macros for file names

#define MOUNT_PATH           "/fs/"
#define FILENAMEONE      MOUNT_PATH "filename1.csv"
#define FILENAMETWO      MOUNT_PATH "filename2.txt"
fd = fopen(FILENAMEONE, "a");

I do not know what is exactly the reason of write a first line to the file. But you not need check if the file exist when you use “+” in the mode argument of the fopen method.
fopen - C++ Reference (cplusplus.com)

Also the FILE object seems to be pointless to have it as global when you not use it as global.

BR, Jan

Hi @JohnnyK , thanks for your reply. I tried to reduce the code but in the process some instructions were deleted, I could do it better. Just now I am reducing the code to isolate the problem but in this step I notice my new code is working but still I must see what was the problem.

Best Regards