Skip to main content
alex_embedded
Associate III
April 12, 2019
Solved

Fatfs create folders

  • April 12, 2019
  • 6 replies
  • 4950 views

Hi All,

I am currently working on creating a file system on an stm32f207, using the nucleo board for the time being while I wait for my custom boards.

The board will have an SD card as well as a USB.

I have made a simple function for creating a folder onto a drive:

FRESULT f_CreateFolder(	const TCHAR* path){
 
	FRESULT fr;
 
	// Create folder/directory
	fr = f_mkdir(path);
	if(fr == FR_OK){
 
		// Success
		// TODO: f_mkdir Something to happen when successful
 
	}
	else{
 
		// Error
		// TODO: f_CreateFolder make directory error
 
	}
 
	return fr;
} // END f_CreateFolder

the "f_mdir" has no calls to which drive it is referring to, so if both SD and USB are mounted, how do I choose which drive to create a folder on??

Finally, I have been succesful with creating a single folder on the SD (yet to try on USB but I can't imagine it being any different) but I am not sure how to create folders within folders, if that makes sense lol.

This works to create folders in the root directory:

 // Mount SD Card
 f_MountDisk(&SDCard, &SDFatFS, SDPath);
 
 HAL_Delay(100);
 
 f_CreateFolder("INIT");
 HAL_Delay(100);
 
 f_CreateFolder("CONFIG");
 HAL_Delay(100);
 
 f_CreateFolder("LOGS");
 HAL_Delay(100);

How can I create folders inside the folders created above, for example have another folder in "LOGS" for specific dates.

Thanks in advance all!! =)

This topic has been closed for replies.
Best answer by Tesla DeLorean

>>Finally, I have been succesful with creating a single folder on the SD (yet to try on USB but I can't imagine it being any different) but I am not sure how to create folders within folders, if that makes sense lol.

f_mkdir("/FOO");

f_mkdir("/FOO/FOO");

f_mkdir("/FOO/FOO/FOO");

I have my f_open() wrapped so that if I get an FR_NO_PATH, I pass the fully qualified path/file to a BuildPath() function that recursively builds out the tree of pieces that don't already exist. Then I retry the f_open()

 res = f_open(&fil, Filename, FA_OPEN_ALWAYS | FA_WRITE);
 
 if (res == FR_NO_PATH)
 {
 BuildPath(Filename); // descend and build missing nodes
 res = f_open(&fil, Filename, FA_CREATE_ALWAYS | FA_WRITE); // try again
 }
 
 if (res == FR_OK)
 {
 ...

6 replies

Tesla DeLorean
Tesla DeLoreanBest answer
Guru
April 12, 2019

>>Finally, I have been succesful with creating a single folder on the SD (yet to try on USB but I can't imagine it being any different) but I am not sure how to create folders within folders, if that makes sense lol.

f_mkdir("/FOO");

f_mkdir("/FOO/FOO");

f_mkdir("/FOO/FOO/FOO");

I have my f_open() wrapped so that if I get an FR_NO_PATH, I pass the fully qualified path/file to a BuildPath() function that recursively builds out the tree of pieces that don't already exist. Then I retry the f_open()

 res = f_open(&fil, Filename, FA_OPEN_ALWAYS | FA_WRITE);
 
 if (res == FR_NO_PATH)
 {
 BuildPath(Filename); // descend and build missing nodes
 res = f_open(&fil, Filename, FA_CREATE_ALWAYS | FA_WRITE); // try again
 }
 
 if (res == FR_OK)
 {
 ...

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
alex_embedded
Associate III
April 12, 2019

Awesome way to go about this!!

Here's a pint to say thank you -> :beer_mug:

Being that an aussie has given you a pint, it is customary for you to neck it all at once, good luck!

Tesla DeLorean
Guru
April 12, 2019

Shotgun...

I just need Amazon to be able to deliver beer, but I do accept gift cards when you run out of virtual beer..

Not totally bullet-proof, but serviceable..

//******************************************************************************
 
char *strmalloc(char *str)
{
 char *s = malloc(strlen(str) + 1);
 if (s)
 strcpy(s, str);
 return(s);
}
 
//******************************************************************************
 
// Top level input is "/FOO/FOO/FOO/BAR.LOG"
 
void BuildPath(char *path) // sourcer32@gmail.com
{
 FRESULT res;
 char *s = strmalloc(path);
 int i = strlen(s);
 
 while(i && s[i-1] != '/') // Find decomposition point
 i--;
 
 if (i) // Move to '/'
 i--;
 
 if (i)
 {
 s[i] = 0; // replace '/' with NUL
 
 res = f_mkdir(s);
 
// printf("res = %d f_mkdir '%s'\n", res, s);
 
 if (res == FR_NO_PATH)
 {
 BuildPath(s); // Drop down a level, and build that
 
 res = f_mkdir(s); // Try again
 
// printf("res = %d f_mkdir '%s' (2nd)\n", res, s);
 }
 
 if (res == FR_OK)
 printf("Created path '%s'\n", s);
 }
 
 free(s);
}
 
//******************************************************************************

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
alex_embedded
Associate III
April 17, 2019

So, I came back to this today and was running some of my test code to backtrack what I had done.

Creating folders within folders now refuses to work, and I haven't touched the "createFolder" function I created!?

f_CreateFolder:

FRESULT f_CreateFolder(	const TCHAR* path){
 
	FRESULT fr;
 
	// Create folder/directory
	fr = f_mkdir(path);
	if(fr == FR_OK){
 
		// Success
		// TODO: f_mkdir Something to happen when successful
 
	}
	else{
 
		// Error
		// TODO: f_CreateFolder make directory error
 
	}
 
	return fr;
} // END f_CreateFolder

Creating a folder in the root directory is still successful:

 f_CreateFolder("/TEST");
 HAL_Delay(20);

And then, creating a folder under "TEST" returns "FR_INVALID_NAME"

 f_CreateFolder("/TEST/SECONDTEST");
 HAL_Delay(20);
 f_CreateFolder("/LOGS/THIRDTEST");
 HAL_Delay(20);

What the hell!? Previously I tried creating "12APR2019" folder inside a folder called "LOGS", creating the "LOGS" folder first and then creating the "12APR2019" next was both successful. What about the folder name is invalid?

alex_embedded
Associate III
April 17, 2019

**UPDATE**

Seems that the limit for the "path" variable in f_mkdir is limited to 14 characters.

fr = f_mkdir(path);

using my f_CreateFolder function (shown above):

f_CreateFolder("/TEST/1234567");

"/TEST/1234567" = 13 characters, returns FR_OK

"/TEST/12345678" = 14 characters, returns FR_OK

"/TEST/123456789" = 15 characters, returns FR_INVALID_NAME

Is this something that can be adjusted or is it a limit I must accept?