6 years, 2 months ago.

ST DISCO-F746NG; Using onboard SDRAM to create filesystem and have it available through USB to PC

Hello,

I have a large amount of data and while I could use UART at high rate, I am wondering if I could create a filesystem on onboard SDRAM and share it to PC though USB. My device and data do not require nonvolatility (i.e. flash), the data is easily regenarated. RAM disk would be the best option for me.

What kind of libraries and SW modules I should look into?

3 Answers

6 years ago.

Have a look at https://os.mbed.com/users/roykrikke/code/BD_SD_DISCO_F746NG maybe this will help with your project.

6 years ago.

You can create a RAM disk using the HeapBlockDevice and mount a FAT file system on it. Since the DISCO-F746NG board is equipped with Ethernet interface you can then create a TFTP server which will allow you to upload files to or download files from the RAM disk. All you need is MBED OS 5 and the TFTPServer library. Below is a sample code that worked for me on a NUCLEO-F767ZI board.

#include "mbed.h"
#include "FATFileSystem.h"
#include "HeapBlockDevice.h"
#include "EthernetInterface.h"
#include "TFTPServer.h"
#include "errno.h"

Serial              pc(USBTX, USBRX);
HeapBlockDevice     bd(192 * 512, 512); // 192 * 512 bytes with a block size of 512 bytes
FATFileSystem       fs("fs");           // FAT file sytem
EthernetInterface   net;                // Ethernet interface
TFTPServer*         server;             // Pointer to a TFTPServer
int                 myPort = 69;        // TFPTServer port

#define USE_DHCP

/**
* @brief
* @note
* @param
* @retval
*/
int main()
{
    // Try to format the filesystem. This should work without the Ethernet.
    pc.printf("Formatting the filesystem... \r\n");

    int err = FATFileSystem::format(&bd, 512);
    pc.printf("%s\r\n", (err ? "Failed :(\r\n" : "OK\r\n"));

    if (err)
        return 1;

    // Try to mount the filesystem. This should work without the Ethernet.
    pc.printf("Mounting the filesystem... \r\n");
    err = fs.mount(&bd);
    pc.printf("%s\r\n", (err ? "Failed :(\r\n" : "OK\r\n"));

    if (err)
        return err;

    // Open a file. This should work without the Ethernet too.
    pc.printf("Opening \"/fs/test.txt\"... \r\n");

    FILE*   fp = fopen("/fs/test.txt", "r+");
    pc.printf("%s\r\n", (!fp ? "Failed :(\r\n" : "OK\r\n"));

    if (!fp)
    {
        // Create the test file if it doesn't exist yet.
        pc.printf("No file found, creating a new file ...\r\n");
        fp = fopen("/fs/test.txt", "w+");
        pc.printf("%s\r\n", (!fp ? "Failed :(" : "OK"));
        if (!fp)
            error("error: %s (%d)\r\n", strerror(errno), -errno);

        for (int i = 0; i < 10; i++)
        {
            pc.printf("\rWriting numbers (%d/%d)... ", i, 10);
            err = fprintf(fp, "    %d\n", i);
            if (err < 0)
            {
                pc.printf("Fail :(\r\n");
                error("error: %s (%d)\n", strerror(errno), -errno);
            }
        }

        pc.printf("\rWriting numbers (%d/%d)... OK\r\n", 10, 10);

        pc.printf("Closing file ");
        fclose(fp);
        printf(" done.\r\n");
    }

    // Connect to the Ethernet
    pc.printf("Connecting to the Ethernet using ");
#ifdef USE_DHCP
    pc.printf("DHCP server ...\r\n");
#else
    pc.printf("fixed IP ...\r\n");
    net.set_network("192.168.1.185", "255.255.255.0", "192.168.1.1");
#endif
    net.connect();
    pc.printf("IP: %s\r\n", net.get_ip_address());
    pc.printf("NetMask: %s\r\n\r\n", net.get_netmask());

    // Create a TFTP server.
    pc.printf("Creating a TFTP server ...\r\n\r\n");
    server = new TFTPServer(&net, myPort);
    pc.printf("%s\r\n", (server ? "OK" : "Failed :("));
    if (!server)
        return 1;
    
    if (server->getState() == TFTPServer::LISTENING)
        pc.printf("The TFTP server is listening at port %d.\r\n", myPort);
    else
    {
        pc.printf("Something went wrong.\r\nThe TFTP server is not listening.\r\n");
        return 1;
    }
    

    int     fileCount = 0;  // incoming files
    char    fileName[256];  // to display filenames

    while (1)
    {
        server->poll();

        if (server->fileCount() > fileCount)
        {
            fileCount = server->fileCount();
            server->getFileName(fileName);
            pc.printf("new file: %s\r\n", fileName);
        }
    }
}

See also the TFTPServerTest example program which is using an SD card as storage place and explains how to upload to or download from the TFTP server.

Hi Zoltan!

I tried using RAM disk / heap block device but couldn't redirect it to point to SDRAM. The on-chip SRAM is too small to hold enough files/data.

posted by Tapio Valli 25 Mar 2018

Hello Tapio,

I'm sorry. I did not mention that the minimum size of the HeapBlockDevice required by the FAT file system was 192 * 512 Bytes = 96 kB. Despite having 320 kB SRAM on a DISCO-F746NG board it seems that the TFT display and the Ethernet interface demand too much SRAM. Maybe you could somehow disable the LCD and get more SRAM for the RAM disk. Otherwise you can use an SD card for storage as suggested by Roy.

posted by Zoltan Hudak 25 Mar 2018
6 years ago.

Beware, the mbed cpu cannot change the data in the file system. There is only one master and that is the PC. The PC may only change the data in the file system RAM (or wahtever memory is used to back the USB MS device) So the file system and data must exist before the USB enumerates the mass storage device.