10 years, 6 months ago.

LPC11U24 - Broken append to SD card log file

Hi, I'm developing a data logger using the LPC11U24 mbed board. The board is connected with a SD Card breakout board through SPI and some I2C sensors.

My application reads sensors data every second and writes these data to a log file every 30 sec (the log file is on the SD Card). The SD Card is formatted FAT32 and I use SDFileSystem to access the SD Card.

I use fopen(fp_name, "a") to open the log file in append mode. Note: I do not close file, I only open the file once at the beginning of the program and then append data to this file.

When I put a clean SD Card and power the mbed board, it starts logging data appending to the log file, but if I power off the mbed board and then re-power the board (without deleting the log file from the SD Card) the data written in the log file are not appended to the end of the file.

This a sample datalog that I obtain when I restart the mbed with an SD Card that already contains a previous log file:

Wrong datalog

...
2014-05-19 11:55:16;24.3;0.00;4.87;0.00;0.00
2014-05-19 11:55:17;24.3;0.00;4.87;0.00;0.00
2014-05-19 11:55:18;24.3;0.00;4.87;0.00;0.00
2014-05-21 13:10:24;26.7;0.00;4.88;0.00;0.00
2014-05-21 13:10:25;26.7;0.00;4.88;0.00;0.00
2014-05-21 13:10:26;26.7;0.00;4.88;0.00;0.00
...
2014-05-21 16:15:21;27.6;0.00;4.88;0.00;0.00
2014-05-21 16:15:22;27.6;0.00;4.88;0.00;0.00
2014-05-21 16:15:23;27.6;0.00;4.88;0.00;0.00
2014-05-19 15:00:19;25.4;0.00;4.87;0.00;0.00
2014-05-19 15:00:20;25.4;0.00;4.87;0.00;0.00
2014-05-19 15:00:21;25.4;0.00;4.87;0.00;0.00
...

As you can see the data recorded on 2014-05-19 are broken and in the middle of those appears the data recorded on 2014-05-21 (that is the day when I power off and then re-power on the board).

I post some code to help understand the problem:

SDLogger Class

SDLogger::SDLogger(uint8_t oid, PinName mosi, PinName miso, PinName sclk, PinName cs) : id(oid), sd(mosi, miso, sclk, cs, sdName)
{
    fp = NULL;
    fp_mon = 0;
    fifoPos = 0;
    memset(fifo, 0, FIFO_SIZE * sizeof(struct rd));
}

bool SDLogger::fileIsOpen()
{
    return (fp != NULL);
}

void SDLogger::openFile(uint16_t year, uint8_t mon)
{
    memset(fp_name, 0, sizeof(fp_name));
    int result = sprintf(fp_name, "/%s/%.02u_%.04u-%.02u.csv", sdName, id, year, mon);
    if (result > 0) {
        fp = fopen(fp_name, "a");
        if (fp != NULL)
            fp_mon = mon;                
    }
}

void SDLogger::closeFile()
{
    fclose(fp);
#if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler
    free(fp);
#endif
    fp = NULL;    
}

void SDLogger::writeFile(struct rd *r)
{
    fprintf(fp, "%.04u-%.02u-%.02u %.02u:%.02u:%.02u;%.1f;%.2f;%.2f;%.2f;%.2f\n", 
        r->rd_year, r->rd_mon, r->rd_mday,  r->rd_hour, r->rd_min, r->rd_sec, 
        r->rd_temp, r->rd_lux, r->rd_volt, r->rd_curr, r->rd_pow);
}

void SDLogger::reset()
{
    if (fileIsOpen()) 
        closeFile();
    fp_mon = 0;
    fifoPos = 0;
    memset(fifo, 0, FIFO_SIZE * sizeof(struct rd));    
}

void SDLogger::append(struct rd *r)
{
    if (fifoPos == FIFO_SIZE) {
        
        // remove oldest record and shift fifo
        for (int i = 1; i < FIFO_SIZE; i++) {
            memcpy(&fifo[i-1], &fifo[i], sizeof(struct rd));
        }
        
        fifoPos--;
    }
    
    memcpy(&fifo[fifoPos], r, sizeof(struct rd));
    
    fifoPos++;
    
    if (fifoPos == FIFO_SIZE) {
        flushQueue();
    }
}

void SDLogger::flushQueue()
{
    for (int i = 0; i < FIFO_SIZE; i++) {
        
        // Check if sd card is inserted
        if (!sdCardPresent) {
            if (fileIsOpen())
                closeFile();
            break; 
        }
         
        // Create one file per month
        if (!fileIsOpen() || fp_mon != fifo[i].rd_mon) {
            if (fileIsOpen()) 
                closeFile();
            openFile(fifo[i].rd_year, fifo[i].rd_mon);
        }
        
        // If error during fopen - exit from loop
        if (!fileIsOpen())
            break;
        
        // Write CSV record to file
        writeFile(&fifo[i]);
    }
    
    // Flush file
    if (fileIsOpen()) 
        fflush(fp);        
    
    fifoPos = 0;
}

From the main, I call only the append(...) method of the SDLogger class.

It seems that the error appears when the mbed re-opens an already existing file (in append mode), because if I plug a clean SD Card and let the board run continuously for days, the data are recorded correctly.

Be the first to answer this question.