This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Writing to SD Card

I can't seem to get this working on my 129x.

I've written a number of wrapper functions to simplify open/read/write operations on the SD card.

void sdcardConfigure() {
        // Configure the device pins
        
        // Enable necessary GPIO peripherals
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
        
        // PF0/PF4-5/PH4/PQ0-2 are used for the SPI flash (on-board and SD card).
        // PH4 selects the SD card and PQ1 selects the on-board SPI flash.
        ROM_GPIOPinConfigure(GPIO_PF0_SSI3XDAT1);
        ROM_GPIOPinConfigure(GPIO_PF4_SSI3XDAT2);
        ROM_GPIOPinConfigure(GPIO_PF5_SSI3XDAT3);
        ROM_GPIOPinConfigure(GPIO_PQ0_SSI3CLK);
        ROM_GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);
        ROM_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4 | GPIO_PIN_5);
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_4);
        ROM_GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_4, GPIO_PIN_4);
        ROM_GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_0 | GPIO_PIN_2);
        ROM_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_1);
        ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, GPIO_PIN_1);
}
uint8_t sdcardFileOpenWrite(char* fileName) {
    FRESULT fr;
    fr = f_open(&g_sFileObject, fileName, FA_WRITE | FA_OPEN_ALWAYS);
    
    if(fr != FR_OK) {
        sdcardLogError(SDCARD_ERROR_FILE,(char *)StringFromFResult(fr));
        return 1; // Error opening file
    }

    // No errors
    return 0;
}
uint8_t sdcardFileAppendLine(char* line) {
    FRESULT fr;

    // Move to the end of the file
    fr = f_lseek(&g_sFileObject, f_size(&g_sFileObject));

    // if error here return error number
    if (fr != FR_OK) {
        sdcardFileClose();
        sdcardLogError(SDCARD_ERROR_FILE,(char *)StringFromFResult(fr));
        return 1; // Seek failure
    }

    // Variable to hold the number of bytes written
    int16_t bw;

    // Write the line to the file
    bw = f_puts(line, &g_sFileObject);

    // if error here return error number
    if (bw == -1) {
        sdcardFileClose();
        sdcardLogError(SDCARD_ERROR_FILE,(char *)StringFromFResult(fr));
        return 2; // Write failed, end of file error
    }

    // No errors
    return 0;
}
uint8_t sdcardFileClose() {
    FRESULT fr;
    fr = f_close(&g_sFileObject);

    if(fr != FR_OK) {
        sdcardLogError(SDCARD_ERROR_FILE,(char *)StringFromFResult(fr));
        return 1; // Close error occurred
    }
    
    // No errors
    return 0;
}
uint8_t sdcardMount(void) {
    FRESULT fr;

    fr = f_mount(0, &g_sFatFs);
    if(fr != FR_OK) {
        sdcardLogError(SDCARD_ERROR_FILE,(char *)StringFromFResult(fr));
        return 1; // Mount error occurred
    }
    
    return 0;
}

int main(void) {
  uint8_t x
  sdcardConfigure();
  x = sdcardMount();
  UARTprintf("mount: %d\n", x);
  x = sdcardFileOpenWrite("/myfile.txt");
  UARTprintf("open: %d\n",x);
  char line[80] = "writing some text";
  x = sdcardAppendLine(line);
  UARTprintf("append: %d\n", x);
  x = sdcardFileClose();
  UARTprintf("close: %d\n", x);
}

For some reason sdcardOpen returns 0 (FR_OK) and sdcardAppendLine returns 2 (EOF error). When I look at the contents of the SD Card, the file was never created. Why would I get an FR_OK from f_open if the file wasn't created?

Note: sdcardLogError() is currently an empty function, shouldn't have any affect

  • Is there an issue with how I'm passing the file name to sdcardFileOpenWrite?

    I just did a test open/write/close

    sdcardConfigure();
    sdcardMount();
    
    UARTprintf("open: %d\n", (int)f_open(&g_sFileObject, "/somefile.log", FA_WRITE | FA_OPEN_ALWAYS));
    UARTprintf("seek: %d\n", (int)f_lseek(&g_sFileObject, f_size(&g_sFileObject)));
    UARTprintf("write: %d\n", f_puts("some test string\n", &g_sFileObject));
    UARTprintf("close: %d\n", (int)f_close(&g_sFileObject));

    that worked as expected. so it seems everything is set up properly and the issue lies inside my wrapper functions.

  • to confuse me even more, this works.

    void testWrite() {
        //UARTprintf("open: %d\n", (int)f_open(&g_sFileObject, "/testfile.log", FA_WRITE | FA_OPEN_ALWAYS));
        UARTprintf("open: %d\n", sdcardFileOpenWrite("tf2.log"));
        //UARTprintf("seek: %d\n", (int)f_lseek(&g_sFileObject, f_size(&g_sFileObject)));
        //UARTprintf("write: %d\n", f_puts("some test string\n", &g_sFileObject));
        UARTprintf("seek/write: %d\n",sdcardFileAppendLine("imagine this worked?"));
        UARTprintf("close: %d\n", (int)f_close(&g_sFileObject));
    
    
  • I think I should give a fuller picture of my code.

    //main file
    #include ...
    #include "sdcard.h"
    
    ...
    
    int main(void) {
       uint8_t var1 = 10;
       uint8_t var2 = 12;
    
       ...
    
       sdcardConfigure();
       UARTprintf("mount: %d\n", sdcardMount());
    
       testWrite(); // works
    
       // intended usage fails
       UARTprintf("open: %d\n", sdcardFileOpenWrite("/mylog.log"));
       char logStr[80];
       
       sprintf(logStr,"LogStr::var1:%d,var2:%d;\n", var1, var2);
       UARTprintf("append: %d\n", sdcardFileAppendLine(logStr));
       UARTprintf("close: %d\n", sdcardFileClose());
    
       ...
    
    }
    //sdcard.h
    ...
    void sdcardConfigure(void);
    void testWrite(void);
    uint8_t sdcardFileOpenWrite(const char* fileName);
    uint8_t sdcardFileAppendLine(char* line);
    uint8_t sdcardFileClose(void);
    uint8_t sdcardMount(void);
    ...
    //sdcard.c
    
    ...
    
    FATFS g_sFatFs;
    DIR g_sDirObject;
    FILINFO g_sFileInfo;
    FIL g_sFileObject;
    FIL g_sErrorFile;
    
    void testWrite() {
        #include "customlib/uart/uartprint.h"
        //PRINTF("open: %d\n", (int)f_open(&g_sFileObject, "/testfile.log", FA_WRITE | FA_OPEN_ALWAYS));
        PRINTF("open: %d\n", sdcardFileOpenWrite("/tf3.log"));
        //PRINTF("seek: %d\n", (int)f_lseek(&g_sFileObject, f_size(&g_sFileObject)));
        //PRINTF("write: %d\n", f_puts("some test string\n", &g_sFileObject));
        PRINTF("seek/write: %d\n",sdcardFileAppendLine("imagine this worked?"));
        PRINTF("close: %d\n", (int)f_close(&g_sFileObject));
    
    }
    
    uint8_t sdcardFileOpenWrite(const char* fileName) {
        FRESULT fr;
        fr = f_open(&g_sFileObject, fileName, FA_WRITE | FA_OPEN_ALWAYS);
        
        if(fr != FR_OK) {
            sdcardLogError(SDCARD_ERROR_FILE,(char *)StringFromFResult(fr));
            return 1; // Error opening file
        }
    
        // No errors
        return 0;
    }
    
    uint8_t sdcardFileAppendLine(char* line) {
        FRESULT fr;
    
        // Move to the end of the file
        fr = f_lseek(&g_sFileObject, f_size(&g_sFileObject));
    
        // if error here return error number
        if (fr != FR_OK) {
            sdcardFileClose();
            sdcardLogError(SDCARD_ERROR_FILE,(char *)StringFromFResult(fr));
            return 1; // Seek failure
        }
    
        // Variable to hold the number of bytes written
        int16_t bw;
    
        // Write the line to the file
        bw = f_puts(line, &g_sFileObject);
    
        // if error here return error number
        if (bw == -1) {
            sdcardFileClose();
            sdcardLogError(SDCARD_ERROR_FILE,(char *)StringFromFResult(fr));
            return 2; // Write failed, end of file error
        }
    
        // No errors
        return 0;
    }
    
    uint8_t sdcardFileClose() {
        FRESULT fr;
        fr = f_close(&g_sFileObject);
    
        if(fr != FR_OK) {
            sdcardLogError(SDCARD_ERROR_FILE,(char *)StringFromFResult(fr));
            return 1; // Close error occurred
        }
        
        // No errors
        return 0;
    }
    
    uint8_t sdcardMount(void) {
        FRESULT fr;
    
        fr = f_mount(0, &g_sFatFs);
        if(fr != FR_OK) {
            sdcardLogError(SDCARD_ERROR_FILE,(char *)StringFromFResult(fr));
            return 1; // Mount error occurred
        }
        
        return 0;
    }
    
    void sdcardConfigure() {
        /* TODO: Should we be using the peripheral definition macros from the
         *       fatfs/port/mmc- files here? Could try to minimize the device
         *       differentiation code. Most other __Configure functions are
         *       accepting a predefined __ to initialize it. Current convention
         *       is to do all differentiation in main. Would it be better to do
         *       it in the __Configure functions instead? */
        #ifdef PART_TM4C123GH6PM
            // Currently no SD Card peripheral
        #elif PART_TM4C129XNCZAD
            // Configure the device pins
            
            // Enable necessary GPIO peripherals
            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
            ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
            
            // PF0/PF4-5/PH4/PQ0-2 are used for the SPI flash (on-board and SD card).
            // PH4 selects the SD card and PQ1 selects the on-board SPI flash.
            ROM_GPIOPinConfigure(GPIO_PF0_SSI3XDAT1);
            ROM_GPIOPinConfigure(GPIO_PF4_SSI3XDAT2);
            ROM_GPIOPinConfigure(GPIO_PF5_SSI3XDAT3);
            ROM_GPIOPinConfigure(GPIO_PQ0_SSI3CLK);
            ROM_GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);
            ROM_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4 | GPIO_PIN_5);
            ROM_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_4);
            ROM_GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_4, GPIO_PIN_4);
            ROM_GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_0 | GPIO_PIN_2);
            ROM_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_1);
            ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, GPIO_PIN_1);
        #endif
    }

    when I run the program I get the following output.

    mount: 0 
    open: 0       // open /tf3.log
    seek/write: 0 // append "imagine this worked?\n"
    close: 0      // close /tf3.log
    open: 0       // says it opened mylog.log but no file created
    append: 2     // EOF error from f_puts
    close: 1      // append failed and already closed it

  • A little further on the trail.

    I created a print function to list details about g_sFileObject.

    After the first call to f_open through sdcardFileOpenWrite I had:

    g_sFileObject
            fil->fs->fs_type: 2
            fil->fs->drv: 0
            fil->fs->id: 1
            fil->id: 1
            fil->flag: 12
            fil->pad1: 0
            fil->fsize: ERRORu
    

    After the second call

    g_sFileObject
            fil->fs->fs_type: 2
            fil->fs->drv: 0
            fil->fs->id: 1
            fil->id: 1
            fil->flag: 3a
            fil->pad1: 0
            fil->fsize: ERRORu

    I'm not sure how the deviation in fil->flag is happening.

    12 indicates FA_WRITE | FA_OPEN_ALWAYS

    3A indicates FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA__WRITTEN

  • following through f_open in ff.c the fil->flag is actually as it should be.

    if it's a newly created file it should be 3A, if it's an existing file 12.

    the mystery continues.

  • A little heavier comparison of g_sFileObject's

    // The file that is happily created and adds a new line
    fileName: /tf4.log
            fil->fs->fs_type: 0x2
            fil->fs->drv: 0x0
            fil->fs->n_rootdir: 0x200
            fil->fs->dirbase: 0x2201
            fil->fs->fsi_flag: 0x0
            fil->fs->id: 0x1
            fil->id: 0x1
            fil->flag: 0x12
            fil->pad1: 0x0
            fil->fsize: 0xb4
            fil->fptr: 0x0
            fil->dir_sect: 0x2202
            *fil->dir_ptr: 0x54
            ((DIR*)fil->dir_ptr)->id: 0x2020
            ((DIR*)fil->dir_ptr)->index: 0x2020
            ((DIR*)fil->dir_ptr)->sclust: 0x20474f4c
            ((DIR*)fil->dir_ptr)->clust: 0x5cc00000

    // The jerk file that doesn't do what I want it to
    fileName: /sht21.log
            fil->fs->fs_type: 0x2
            fil->fs->drv: 0x0
            fil->fs->n_rootdir: 0x200
            fil->fs->dirbase: 0x2201
            fil->fs->fsi_flag: 0x0
            fil->fs->id: 0x1
            fil->id: 0x1
            fil->flag: 0x3a
            fil->pad1: 0x0
            fil->fsize: 0x0
            fil->fptr: 0x0
            fil->dir_sect: 0x2202
            *fil->dir_ptr: 0x53
            ((DIR*)fil->dir_ptr)->id: 0x2031
            ((DIR*)fil->dir_ptr)->index: 0x2020
            ((DIR*)fil->dir_ptr)->sclust: 0x474f4c
            ((DIR*)fil->dir_ptr)->clust: 0x5cc00000

  • As it turns out. The problem wasn't in the wrapper functions. Something was happening at the sprintf call that I assume was blowing up the stack.

    I'm still confused as to why the file wasn't created, since the sprintf didn't occur until after sdcardFileOpenWrite was called. I was also able to print the sprintf variable, after it was created, without issue.

    Everything worked after replacing the sprintf with a simple string. Looks like I'm going to need to figure out a different way to write my variable values.

  • I'm looking at replacing sprintf with one of the following.

    https://github.com/mludvig/mini-printf 's snprintf (which is throwing a pile of compile errors)

    or 

    http://elm-chan.org/fsw/strf/xprintf.html 's xsprintf (same guys that made FatFs)

    any experience with either of these?

    I'm doing a whole lot of talking to myself in here.

  • ROM_Jamie said:
    I'm doing a whole lot of talking to myself in here.

    Feel your pain - but our group avoids most all, "new issue devices" until dust has settled - path is clear.

    Might it prove useful for you to run very similar experiments via more mainstream, TM4C123xxx device?  The 129 is in the new/minority usage category - and some here (i.e. those breathing) have noted procurement issues.  The 123 part may expand the population of those able/willing/direct experienced enough to assist.

    Note that past SD card users - here & at other ARM vendors - experienced issues w/"certain" SD cards.  Switching to another brand - and another data capacity - may extend your issue base.

    The fact that vendor has remained silent is curious - may signal that assistance is being sought (one hopes) but that silence is, "never good" and so much less caring than simple, "Heard your plea - we're "in process" - plz. standby..."

  • I have a 123 but don't have an SD card to connect to it at the moment (in the mail) unless I tried to wire it to the 129. I was thinking the 129 would be better for getting used to SD operations since there is one on the board. Less of me worrying about wiring/pin setup, more code dev.

    In the end it seems I've managed to solve the issue by switching out sprintf for xsprintf (http://elm-chan.org/fsw/strf/xprintf.html) indicating I was probably running into stack errors.

    Though the behaviour of the functions around the sprintf call still confuses me.

    I'll take your advice though, once I have the parts I need I'll try to do the majority of my dev on the 123 and then move it to the 129.