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.

MSP430FR5994: need some guidance on FATFS operation

Part Number: MSP430FR5994

I am struggling understanding how the struct FIL gets its pointer to the filesystem (FATFS).

In the code sample, SDCardLib instantiates the filesystem with: 

FATFS fatfs;  //FatFs handle for current FatFs operation session

and just prior to that, the  FIL struct was instantiated as

static FIL fil;

fil holds the *fs pointer to the FATFS filesystem.

I understand that  f_open() is suppose to populate an empty fil object (It takes an empty fil object and a pointer to the path/filename), 

If so, then how does f_open()  get the filesystem fatfs handle (created in SdCardLib) so that it can assign it to the *fs pointer  in fil? If f_open() doesn't fill in the fs pointer, then how did FIL know where the pointer was if the SDCardLib object (holding the fatfs handle) was instantiated afterwards?

The ChaN website has a lot of useful information but I haven't found where it describes how FIL interacts with FATFS.

Some guidance here is most welcomed. thank you. 

  • I found an example code on the ChaN website that shows where I need some guidance.  How did the fil object get the filesystem handle (*fs) ? Was the handle assigned at the time when the fil object was created? If so, how did the compiler  know which fatfs session to assign to the *fs pointer ( assuming I instantiated more than one FATFS object? Was it assigned by the f_mount(), if so how did f_mount() get the reference to &fil?

    thanks

    /* Read a text file and display it */
    
    FATFS FatFs;   /* Work area (filesystem object) for logical drive */
    
    int main (void)
    {
        FIL fil;        /* File object */
        char line[100]; /* Line buffer */
        FRESULT fr;     /* FatFs return code */
    
    
        /* Register work area to the default drive */
        f_mount(&FatFs, "", 0);
    
        /* Open a text file */
        fr = f_open(&fil, "message.txt", FA_READ);
        if (fr) return (int)fr;
    
        /* Read every line and display it */
        while (f_gets(line, sizeof line, &fil)) {
            printf(line);
        }
    
        /* Close the file */
        f_close(&fil);
    
        return 0;
    }

     

  • I think I found my answer. The association of filesystem is done through f_mount(). f_mount() takes three parameters, the first parameter is a reference to the &fatfs object which is a struct which holds the filesystem work area. The second parameter is a path name of the form "0: filename" or "1: filename" where the first two characters (a numeric followed by a colon) represents a logical drive number. The absence of a numeric and colon mean the logical drive is the default drive ("0:"). The third parameter taken by f_mount() is an initialization option. 

    Thus after f_mount() the logical drive is now associated with fatfs object. In the code above the f_mount() second parameter doesn't have a logical drive numeric followed by a colon, thus it is defaults to 0:  Similarly, the second parameter of f_open()  also uses the default drive 0 (it doesn't have a numeric followed by a colon). The bottom line is that f_open() knows the logical drive mounted by f_mount() and is now able to associate the *fs pointer in fil with &fatfs. 

    Below is an example where the logical drives are explicitly specified ("0:" and "1:").

    /* Copy a file "file.bin" on the drive 1 to drive 0 */
    
    int main (void)
    {
        FATFS fs0, fs1;      /* Work area (filesystem object) for logical drives */
        FIL fsrc, fdst;      /* File objects */
        BYTE buffer[4096];   /* File copy buffer */
        FRESULT fr;          /* FatFs function common result code */
        UINT br, bw;         /* File read/write count */
    
    
        /* Register work area for each logical drive */
        f_mount(&fs0, "0:", 0);
        f_mount(&fs1, "1:", 0);
    
        /* Open source file on the drive 1 */
        fr = f_open(&fsrc, "1:file.bin", FA_READ);
        if (fr) return (int)fr;
    
        /* Create destination file on the drive 0 */
        fr = f_open(&fdst, "0:file.bin", FA_WRITE | FA_CREATE_ALWAYS);
        if (fr) return (int)fr;
    
        /* Copy source to destination */
        for (;;) {
            fr = f_read(&fsrc, buffer, sizeof buffer, &br);  /* Read a chunk of source file */
            if (fr || br == 0) break; /* error or eof */
            fr = f_write(&fdst, buffer, br, &bw);            /* Write it to the destination file */
            if (fr || bw < br) break; /* error or disk full */
        }
    
        /* Close open files */
        f_close(&fsrc);
        f_close(&fdst);
    
        /* Unregister work area prior to discard it */
        f_mount(0, "0:", 0);
        f_mount(0, "1:", 0);
    
        return (int)fr;
    }

  • Hello James,

    Thanks for your post and share the solution with the community.

    Thanks,

    Yiding

**Attention** This is a public forum