Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

avoid SD card corruption in ansi C

I am currently working on an embedded Linux device for data logging. The Linux device is plugged into a CANbus and writes the traffic to an SD card.

From time to time the SD card corrupts and is mounted read-only. This behavior needs to be avoided.

The file system is FAT (the SD card should stay be readable by windows systems).

The embedded device can power fail any time, so I need a safe way to write to the SD card from my C program.

As I am not really into C, I rely on a program called "candump" which basically prints the canmessages to stdout in this format:

<0x006> [8] 77 00 00 00 00 00 00 00

My C program basically opens the candump program, reads from stdout, adds a timestamp and removes unnecessary chars:

1345836055.520 6 7700000000000000


while(running)
{
    if (filename != NULL)
    {
        fp_log = fopen(filename, "a");
        if (!fp_log) 
        {
            perror("fopen");
            exit (EXIT_FAILURE);
        }  
    }  

    fgets(line, sizeof(line)-1, fp);

    /* reset the row_values so they are always correctly initialized */
    row_identifier = 0;

    if (strchr(line,'<') != NULL)
    {
        /* creating a buffer char to store values for casting char to int*/
        buffer_ident[0] = line[4];
        buffer_ident[1] = line[5];

        /* cast buffer e.g. {'1','0','\0'} to int: 10 */
        row_identifier = strtol(buffer_ident,NULL,10);

        /* heartbeat of the CANBUS PLC */
        if(row_identifier == 80)
        {
            /* return pong on identifier 81 to the PLC */
            //system("cansend can0 -i 81 1 > /dev/null");
        }
        else
        {
            gettimeofday(&tv,NULL);
            fprintf(fp_log,"%d.%03d ", tv.tv_sec, tv.tv_usec/1000);
            fprintf(fp_log,"%d ",row_identifier);

            /* rowlenght > 11 = data part is not empty */
            row_lenght = strlen(line);
            if (row_lenght>11)
            {
                int i=0;
                for (i=11;i<row_lenght;i++)
                    /* remove spaces between the data to save space and copy data into new array */
                    if (isspace(line[i]) == 0)
                        fprintf(fp_log,"%c",line[i]);
            fprintf(fp_log,"\n");   
            }
        }
    }
    fclose(fp_log);

}

The code snippet above works fine, its just that I get SD card corruption.

Solution

I ended up using ext3 as the file system with standard mount options. No problems any more

like image 412
user1320852 Avatar asked Nov 12 '22 22:11

user1320852


1 Answers

The corruption probably happens because the OS didn't complete its write operations on the FAT filesystem. As correctly pointed out by J-16 SDiZ you can try to mitigate the problem doing sync from time to time to force the OS to write changes on the filesystem.

However, you are having this kind of problems because you are not using a journaled filesystem (such as Ext3 or NTFS. Another thing to do, could be to fsck the filesystem every boot and then explicitly forcing a rw remount to keep the mountpoint clean and writeable.

like image 132
Avio Avatar answered Nov 15 '22 11:11

Avio