cancel
Showing results for 
Search instead for 
Did you mean: 

FATFS SDIO auto-increment File Name problem

martinj3456
Associate III
Posted on December 13, 2015 at 16:54

Hello all,

I am new here and struggling to write a clean for creating a file with auto-increment name after the power on. My purpose is to save buffer data in .BIN format, power off system, start a new session when necessary and save new sensor data in new .BIN file. I have started in this way:

FRESULT res;

FILINFO fno;

FIL fil;

DIR dir;

FATFS fs32;

char* path = '''';

UINT BytesWritten;          // SD card write Byte Count

uint16_t ReceiveData_16[8192];   // 16-bit Data Buffer

#if _USE_LFN

        static char lfn[_MAX_LFN + 1];

#endif

#if _USE_LFN

        fno.lfname = lfn;

        fno.lfsize = sizeof(lfn);

#endif

void SD_Write(void)

{        

    char str[];

    char *s = str;

    char *fn;

    

    if (f_opendir(&dir, path)== FR_OK)  

    {

      while(1)

      {                  

        res = f_readdir(&dir, &fno);   // Read Directory for all files

        if ((res != FR_OK) || (fno.fname[0] == 0))  // Break loop after all file read

          break;

#if _USE_LFN

        fn = *fno.lfname ? fno.lfname : fno.fname;  // Store File Names

#else

        fn = fno.fname;

#endif

    strcpy(s, fn);  

      }                 

    }

        

        len= strlen(s);

        

        // Need to increment file name, say, ''073.BIN'' to ''074.BIN'' file

        

        if (s[len-5]=='9')  

        {

            s[len-5]='0';        

            if (s[len-6]=='9')

            {

                s[len-6]='0';    

            }

            else

            {

                s[len-6]=s[len-6]+1;

            }        

        }

        else

        {        

        s[len-5]=s[len-5]+1;

        }

        //Buffer write with new file name

        

 if (f_open(&fil, str, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)

 {

    f_lseek(&fil, fil.fsize);

    f_write(&fil, ReceiveData_16, sizeof(ReceiveData_16), &BytesWritten);

    f_close(&fil);

 }

}

The issue is it'll not work with a blank directory. Can anyone suggest me a clean code in this regard. I apologize for my poor coding logic.

Thank you for your time.
7 REPLIES 7
Posted on December 13, 2015 at 17:46

The file system does not guarantee in order files. You'll need to enumerate all the files, and find the one with the largest  123.BIN format. ie parse each file name, check the format, pull out the index number, do a max() with the current largest starting with -1. Once you have gone through the directory sprintf(filename, ''%03d.BIN'', maxindex + 1);

Incrementing the ASCII digits seems unduly awkward

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
martinj3456
Associate III
Posted on December 13, 2015 at 18:21

Thank you.. Initially I thought in the following way(messed with &fil pointer):

    FIL fil1,fil2;      

    char line[3];    

    FRESULT fr1;    

    FRESULT fr2;    

    char file_name_str[7];

    char file_name_str1[7];

    int file_name;

    char file_ext[4]= ''.BIN'';

    UINT *data;

    

    ...........

void New_SD_write(char file_name_with_ext[7]){

     if (f_open(&fil, file_name_with_ext, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)

   {

    f_lseek(&fil, fil.fsize);

    f_write(&fil, BufferNow, sizeof(BufferNow), &BytesWritten9);

    f_close(&fil);

   }

}

 

void SD_Init(void)

{

   // Open a  file 000.bin

  fr1 = f_open(&fil1, ''000.BIN'', FA_READ);

    if (fr1 == FR_NO_FILE){

     fr2 = f_open(&fil2, ''000.BIN'', FA_WRITE);

        if (fr2 == FR_OK){

             sprintf(line, ''%3d'', 001); // convert to string

 

        fr2= f_write(&fil2,line,sizeof(line),data);  

             f_close(&fil2);

            

        //creat new file named 001.bin  

         

              New_SD_write(''001.BIN'');

         }

    }else{

     

           fr1 = f_read(&fil1,line,sizeof(line),data);     

           file_name = (int)line;        

               file_name=file_name+1;

               sprintf(file_name_str, ''%3d'', file_name); // convert to string

               f_close(&fil1);

              

               strcat(file_name_str,file_ext);     

              // open the 000.bin file in write mode

               fr1 = f_open(&fil1, ''000.BIN'', FA_WRITE);

               fr1= f_write(&fil1,line,sizeof(line),data);     

      

              New_SD_write(file_name_str);          

    }

    

    f_close(&fil1);

}

int main()

{

  ........

 

  NVIC_SDIO_Configuration();

  memset(&fs32, 0, sizeof(FATFS));

  res = f_mount(0, &fs32);

  memset(&fil1, 0, sizeof(FIL));

  SD_Init();

  ...........

}

Would I implement your direction here? Do you have any sample code?

 Thank you again.
Posted on December 13, 2015 at 21:00

Do you have any sample code?

I'm a developer, I just write code to do what I need to the specification Something like this should be serviceable, though I'm not sure 1000 is big enough

void New_SD_write(char *filename)
{
UINT BytesWritten;
FIL fil;
if (f_open(&fil, filename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
{
f_lseek(&fil, fil.fsize); // Should always be zero if creating
f_write(&fil, BufferNow, sizeof(BufferNow), &BytesWritten);
f_close(&fil);
}
}
int GetNextIndex(char *path)
{
DIR dir;
FILINFO fno;
int i, index = -1;
if (f_opendir(&dir, path) == FR_OK)
{
while(1)
{
if ((f_readdir(&dir, &fno) != FR_OK) || (fno.fname[0] == 0))
break;
if ((strstr(fno.fname, ''.BIN'') != NULL) && (sscanf(fno.fname, ''%d'', &i) == 1))
if (i > index) index = i;
}
}
return(index + 1);
}
{
char filename[16]; // enough space for characters and terminating NUL
sprintf(filename, ''%03d.BIN'', GetNextIndex('''') );
New_SD_write(filename);
}

I think you need to review the chapter on strings and pointers, you need enough space to accommodate the string, however large it may expand, and the NUL added to the end. Subroutines don't need to specify fixed length strings, it's very inflexible.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
martinj3456
Associate III
Posted on December 14, 2015 at 02:21

Thank you Clive1. Its working fine.. I appreciate your time spending here.

martinj3456
Associate III
Posted on December 19, 2015 at 20:26

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6ix&d=%2Fa%2F0X0000000bu0%2F2EDZPeLHxy6OiORnd2YqjNIXubsQlJ5s1UVxwHd0GIY&asPdf=false
Posted on December 20, 2015 at 01:14

The purpose of using pointers would be to avoid replication, not create it.

I don't understand why filename needs 10000 characters, or why it's referenced with &filename, it could be simply passed as filename

 

 

Consider int i[2], where flag is 0 or 1, refer as i[flag], buffer[flag]

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
martinj3456
Associate III
Posted on December 20, 2015 at 05:39

Thank you Clive for the correction. Could you suggest any simpler way to switch buffer for storage and SDIO write. Thank you in advance.