Transfer a file from USB to SD card

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Transfer a file from USB to SD card

4,379 Views
andreas_anderss
Contributor I

Hi!

I'm trying to figure out how to transfer a file from a USB memory to the SD card that is mounted on the MCU FRDM-K64 but dont know realy where to begin.

I have looked in to the files in the example usb_host_msd_fatfs that i could find in the SDK for FRDM-K64 but have not really figured out how it works, and the documentation that comes with the example is not enough for me to understand.

The problem i want to solve is that when i attach an USB memory to MCU i want it to automaticly transfer a file named "test.txt" and store it on the SD card.

Tags (2)
0 Kudos
11 Replies

3,712 Views
scottm
Senior Contributor II

Hi Andreas,

There's no copy function built in to FatFs - you need to open the source file, create the destination file, and read from one and write to the other until it's done.  Here's my very simplistic FatFs file copy shell command:

SHELL_CMD(COPY, 0, "<src> <dest> Copy file")
{
    FIL fin;
    FIL fout;
    FRESULT res;
    char buf[512];
    UINT br;
    UINT bw;

    if (argc > 2)
    {
        res = f_open(&fin, argv[1], FA_READ);
        if (res != FR_OK)
        {
            printf("%s: Error opening source: ", argv[0]);
            print_fatfs_error(res);
            return 1;
        }
        res = f_open(&fout, argv[2], FA_WRITE | FA_CREATE_ALWAYS);
        if (res != FR_OK)
        {
            printf("%s: Error opening destination: ", argv[0]);
            print_fatfs_error(res);
            return 1;
        }
        do
        {
            res = f_read(&fin, buf, sizeof(buf), &br);
            if ((res == FR_OK) && br)
            {
                res = f_write(&fout, buf, br, &bw);
                if (res != FR_OK)
                {
                    printf("%s: Error writing: ", argv[0]);
                    print_fatfs_error(res);
                    f_close(&fin);
                    f_close(&fout);
                    return 1;
                }
            }
        } while ((res == FR_OK) && br);
        f_close(&fin);
        f_close(&fout);
    }
    else
    {
        printf(ERRSTR_MISSING_OPERAND);
    }
    return 0;
}

All this does is create the destination, and read up to 512 bytes of data at a time from the source and write it to the destination until it's done.

Hope that helps!

Scott

0 Kudos

3,712 Views
mjbcswitzerland
Specialist V

Scott

I don't know how good FatFS is at copying from one media to another - your code copies a file on the same media but not between SD card and memory stick (or the reverse).

Regards

Mark

0 Kudos

3,712 Views
scottm
Senior Contributor II

Hi Mark,

I've only ever used multiple physical drives in the demo projects, but FatFs lets you mount multiple drives.  Your diskio.c implementation provides the interface to the underlying media.  If you open a source file one one drive, and a destination on another, FatFs routes the requests appropriately.  Here's the official FatFs example for copying from one drive to another:

/* 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;
}
0 Kudos

3,712 Views
andreas_anderss
Contributor I

Thank you for your help so far! What library is it that i need to include to get to FATFS, FIL, FRESULT..?

In general where can i find the documentation for the different libraries NXP developed?

0 Kudos

3,712 Views
scottm
Senior Contributor II

Those are all part of FatFs, which is a common FAT file system library.  The name of the demo you gave (usb_host_msd_fatfs) has 'fatfs' in it, so it should have FatFs already in the project.

If I knew where to reliably find documentation on NXP's stuff, I wouldn't be posting and complaining here as often.  Some of it you have to get from the MCUX SDK dashboard.  Some things just aren't documented.

0 Kudos

3,712 Views
andreas_anderss
Contributor I

Hahah okay. Yeah it is really hard to find answers on their site.

I found out how to reference to all the types you used in your example.

Can you explain to me what components i need to get this to work. From their example project as i mentioned earlier i found out that they have a USB host implemented.. How am i supposed to know that i need a USB host? :smileysilly: It feels like i'm starting from the end and always find more and more stuff i need to figure out but i would like some base knowledge to start from the beginning instead.

0 Kudos

3,712 Views
scottm
Senior Contributor II

I suppose the documentation assumes some knowledge of USB.  USB is a host-driven protocol, where transfers are all initiated by the host, so anything you want to connect a USB device to needs to be a USB host.  I haven't used the Kinetis host stack (except for running some examples) so I really don't know the specifics, but the examples should get you to the point where you can mount a USB flash drive and copy files from it.

The book 'USB Complete'  is a good introduction to USB if you want to get more into the details.  You probably don't need to know all of that for what you're describing, though - you don't need to know how to create or interpret a device descriptor, for example, because mass storage devices are already supported by the stack and should just work.

0 Kudos

3,712 Views
mjbcswitzerland
Specialist V

Hi Guys

I have attached a binary file that allows transferring data between the SD card and a memory stick on the FRDM-K64F. Also I have made a short video showing it in action at https://youtu.be/VJ7YveF4_8g (which uses the same binary file).

As shown, this is a configuration that can be set for any Kinetis board with an SD card socket (either using the SDHC controller or SPI) and USB host. When using a memory stick with the FRDM-K64F the jumper J21 has to be set so that the board delivers 5V to the connected USB device. This is a very simple circuit (no protection) and so is a bit sensitive - either plug in the USB device quickly to avoid the power bouncing or power/reset the board with the device already connected.

From the video it should be seen that the solution is a complete solution with much more capabilities that the simple libraries. Since it is DOS-like the interface is also easy to control, even between multiple storage media.

Regards

Mark

Finally I also added a very short video (without the talking and explanation) showing how the same is done directly in Visual Studio where the FRDM-K64F (the K64 including its USB, SDHC, interrupts, DMA etc.) plus the USB memory stick and SD card are emulated in approx. real time (which makes development of such things massively faster and simper than directly on the board).

P.S. Most of this is also available in the (free) open source version on GitHub (including the simulation) so even developers only allowed to use open source code can quite simply do the same.

0 Kudos

3,712 Views
charles2
Contributor II

Hi Mark,

Can I apply this on FRDM-K66 with simple head file configurations changed? Also, K66 has high speed USB port, I am not sure if I can change it somewhere to boost the speed.

0 Kudos

3,712 Views
mjbcswitzerland
Specialist V

Hi Scott

That sounds reasonable. Andreas will thus be able to to do what he needs with ease.

Regards

Mark

0 Kudos

3,712 Views
mjbcswitzerland
Specialist V

Hi

If you don't find a solution you can fall back on the uTasker project since it contains all that is needed for USB from/to SD card on the FRDM-K64F:

http://www.utasker.com/kinetis/FRDM-K64F.html

All code is open source and allows the complete operation to be simulated.
USB: http://www.utasker.com/docs/uTasker/USB_User_Guide.PDF
SD card: http://www.utasker.com/docs/uTasker/uTasker_utFAT.PDF

Here is reference code to do it:

#define DISK_COUNT   2                                   // disk C is memory stick, disk D is SD card
static UTDIRECTORY *ptr_utDirectory[DISK_COUNT] = {0};   // pointer to a directory object


UTFILE utFileSD;                                        // local file objects
UTFILE utFileUSB;

ptr_utDirectory[DISK_C] = utAllocateDirectory(DISK_C, 0); // allocate a directory for use by this module associated with C: (memory stick) no need for path name string length
ptr_utDirectory[DISK_D] = utAllocateDirectory(DISK_D, 0); // allocate a directory for use by this module associated with D: (SD card) no need for path name string length

if (utOpenDirectory(0, ptr_utDirectory[DISK_D]) != UTFAT_SUCCESS) { // open the root directory
    return; // SD card not yet mounted - try again later
}
if (utOpenDirectory(0, ptr_utDirectory[DISK_C]) != UTFAT_SUCCESS) { // open the root directory
    return; // memory stick not yet mounted - try again later
}


if ((utOpenFile("InputFileName.txt", &utFileSD, ptr_utDirectory[DISK_D], UTFAT_OPEN_FOR_READ) == UTFAT_PATH_IS_FILE) {
    // If the source file exists
    //
    fnDebugMsg("Source file found: ");
    fnDebugDec(utFileSD.ulFileSize, 0);
    fnDebugMsg(" Bytes\r\n");

    if ((utOpenFile("USB_file_name.txt", &utFileUSB, ptr_utDirectory[DISK_C], (UTFAT_OPEN_FOR_WRITE | UTFAT_CREATE | UTFAT_TRUNCATE)) == UTFAT_PATH_IS_FILE) {
        // New file created or existing will be overwritten
        //
        unsigned char ucBuffer[1024];
        fnDebugMsg("Copying file from SD card to USB stick:");
        while (utFileUSB.ulFileSize < utFileSD.ulFileSize) {
            utReadFile(&utFileSD, ucBuffer, sizeof(ucBuffer);       // read blocks of data from file on SD card and save to the file on USB stick
            utWriteFile(&utFileUSB, ucBuffer, sizeof(ucBuffer);
            fnDebugMsg(".");                                        // show activity
            if (utFileSD.usLastReadWriteLength < sizeof(ucBuffer) { // end of file reached
                break;
            }
        }
    }
    fnDebugMsg("\r\nCopy complete\r\n");
    utCloseFile(&utFileSD);
    utCloseFile(&utFileUSB);
}

The SD card and memory stick are mounted automatically by the uTasker OS and so nothing else is needed.

Regards

Mark

- Better, faster, cheaper Kinetis developments for professional at: http://www.uTasker.com

0 Kudos