cancel
Showing results for 
Search instead for 
Did you mean: 

FATfs on STM32F767 and external Flash

AShel.1
Associate III

I'm using FATfs library for implementing file system on external flash.

Flash is 16MB memory where I can erase minimum of 4kb subsector and total no of subsectors are 4096, so there will be 1 sector per cluster. I've created 2 files

but I see both files are assigned with same sector no i.e sector 10.

So if I write 2nd file data written into first file gets erased.

Do we've to assign sector nos manually?

 /* Create and Open a new text file object with write access */
	    if(f_open(&MyFile, "0:/0:/STM.TXT.TXT", FA_READ | FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)//FA_CREATE_ALWAYS | FA_WRITE
	    {
	      /* 'STM32.TXT' file Open for write Error */
	      Error_Handler();
	    }
	    else
	    {
	      /* Write data to the text file */
	      res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&byteswritten);
 
	      if((byteswritten == 0) || (res != FR_OK))
	      {
	        /* 'STM32.TXT' file Write or EOF Error */
	        Error_Handler();
	      }
	      else
	      {
	        /* Close the open text file */
	      
	        		if(f_open(&MyFile2, "0:/RTM.TXT", FA_READ | FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)//FA_CREATE_ALWAYS | FA_WRITE
	        	    {
	        	      /* 'STM32.TXT' file Open for write Error */
	        	      Error_Handler();
	        	    }
	        /* Open the text file object with read access */
	         else
	        {
	        	res = f_write(&MyFile2, wtext2, sizeof(wtext2), (void *)&byteswritten);
 
	        		      if((byteswritten == 0) || (res != FR_OK))
	        		      {
	        		        /* 'STM32.TXT' file Write or EOF Error */
	        		        Error_Handler();
	        		      }
	        		   
	          /* Read data from the text file */
	        		      f_close(&MyFile);
	        		      	        	  f_close(&MyFile2);
	        f_open(&MyFile, "0:/STM.TXT", FA_READ | FA_OPEN_EXISTING);
	          res = f_read(&MyFile, rtext, sizeof(rtext), (void *)&bytesread);
	          f_open(&MyFile2, "0:/RTM.TXT", FA_READ | FA_OPEN_EXISTING);
	          res = f_read(&MyFile2, rtext2, sizeof(rtext2), (void *)&bytesread);
	          if((bytesread == 0) || (res != FR_OK))
	          {
	             //'STM32.TXT' file Read or EOF Error
	            Error_Handler();
	          }

Thanks,

1 ACCEPTED SOLUTION

Accepted Solutions
Haithem Rahmani
ST Employee

Hi,

Just a 2 cents comment.

Using the FatFs with external Flash is not really recommended, because FatFs doesn't manage either wear leveling or bad blocks.Thus you may get you flash quickly damaged. So If you don't have any particular constraint for using FatFs I'd suggest the littlefs as a better alternative.

regards

Haithem.

View solution in original post

8 REPLIES 8

Should work with a sector size of 4K configured in FatFs. Make sure to have enough stack and buffering to cover the larger expectations.

Would want to use most current release of FatFs

Show code instrumentation in DISKIO

Show log of read/write sector requests serviced by DISKIO

Ideally have the DISKIO code generate a CRC of sectors as read/written so you can confirm that the same data you wrote is recovered later.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

I thought if we create multiple files in same drive then sector no assigned to file object should be different

for example

file1 - "0:/STM.TXT"

file2 - "0:/RTM.TXT"

then STM.TXT should start from sector no 8 as sector no 0 to 7 are for storing FAT and directory entry data then RTM.TXT file should start from sector 9,

but both files STM.TXT and RTM.TXT are assigned with sector no 8, I've checked in debug mode that fp->clst is 0 and fp->sect is 8.

I've one doubt in f_open function are loaded with default cluster no, so for every new file created it'll assign same sector no.

cl = LD_CLUST(dir); /* Get start cluster */

ST_CLUST(dir, 0); /* cluster = 0 */

my question do we need to change this code and assign sector no as per the files we create.

if my 1st file I want to create for size 8kb then I will have to assign sector no 8 to it

for 2nd file I'll have to assign sector no 10. so above lines will be changed to

cl = (first_file_size) + LD_CLUST(dir); /* Get start cluster */

ST_CLUST(dir, cl); /* cluster = 0 */

here fist_file_size will be 2 as first file created was of 8kb size.

FRESULT f_open (
	FIL *fp,			/* Pointer to the blank file object */
	const TCHAR *path,	/* Pointer to the file name */
	BYTE mode			/* Access mode and file open mode flags */
)
{
	FRESULT res;
	DIR dj;
	BYTE *dir;
	DEF_NAMEBUF;
 
	fp->fs = 0;			/* Clear file object */
 
#if !_FS_READONLY
	mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW;
	res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ));
#else
	mode &= FA_READ;
	res = chk_mounted(&path, &dj.fs, 0);
#endif
	INIT_BUF(dj);
	if (res == FR_OK)
		res = follow_path(&dj, path);	/* Follow the file path */
	dir = dj.dir;
 
#if !_FS_READONLY	/* R/W configuration */
	if (res == FR_OK) {
		if (!dir)	/* Current dir itself */
			res = FR_INVALID_NAME;
#if _FS_SHARE
		else
			res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
#endif
	}
	/* Create or Open a file */
	if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
		DWORD dw, cl;
 
		if (res != FR_OK) {					/* No file, create new */
			if (res == FR_NO_FILE)			/* There is no file to open, create a new entry */
#if _FS_SHARE
				res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
#else
				res = dir_register(&dj);
#endif
			mode |= FA_CREATE_ALWAYS;		/* File is created */
			dir = dj.dir;					/* New entry */
		}
		else {								/* Any object is already existing */
			if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) {	/* Cannot overwrite it (R/O or DIR) */
				res = FR_DENIED;
			} else {
				if (mode & FA_CREATE_NEW)	/* Cannot create as new file */
					res = FR_EXIST;
			}
		}
		if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {	/* Truncate it if overwrite mode */
			dw = get_fattime();					/* Created time */
			ST_DWORD(dir+DIR_CrtTime, dw);
			dir[DIR_Attr] = 0;					/* Reset attribute */
			ST_DWORD(dir+DIR_FileSize, 0);		/* size = 0 */
			cl = LD_CLUST(dir);					/* Get start cluster */
			ST_CLUST(dir, 0);					/* cluster = 0 */
			dj.fs->wflag = 1;
			if (cl) {							/* Remove the cluster chain if exist */
				dw = dj.fs->winsect;
				res = remove_chain(dj.fs, cl);
				if (res == FR_OK) {
					dj.fs->last_clust = cl - 1;	/* Reuse the cluster hole */
					res = move_window(dj.fs, dw);					
				}
			}
		}
	}
	else {	/* Open an existing file */
		if (res == FR_OK) {						/* Follow succeeded */
			if (dir[DIR_Attr] & AM_DIR) {		/* It is a directory */
				res = FR_NO_FILE;
			} else {
				if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
					res = FR_DENIED;
			}
		}
	}
	if (res == FR_OK) {
		if (mode & FA_CREATE_ALWAYS)			/* Set file change flag if created or overwritten */
			mode |= FA__WRITTEN;
		fp->dir_sect = dj.fs->winsect;			/* Pointer to the directory entry */
		fp->dir_ptr = dir;
#if _FS_SHARE
		fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
		if (!fp->lockid) res = FR_INT_ERR;
#endif
	}
 
#else				/* R/O configuration */
	if (res == FR_OK) {					/* Follow succeeded */
		if (!dir) {						/* Current dir itself */
			res = FR_INVALID_NAME;
		} else {
			if (dir[DIR_Attr] & AM_DIR)	/* It is a directory */
				res = FR_NO_FILE;
		}
	}
#endif
	FREE_BUF();
 
	if (res == FR_OK) {
		fp->flag = mode;					/* File access mode */
		fp->sclust = LD_CLUST(dir);	/* File start cluster */
		fp->fsize = LD_DWORD(dir+DIR_FileSize);	/* File size */
		fp->fptr = 0;						/* File pointer */
		fp->dsect = 0;
#if _USE_FASTSEEK
		fp->cltbl = 0;						/* Normal seek mode */
#endif
		fp->fs = dj.fs; fp->id = dj.fs->id;	/* Validate file object */
	}
 
	LEAVE_FF(dj.fs, res);
 
}

Haithem Rahmani
ST Employee

Hi,

Just a 2 cents comment.

Using the FatFs with external Flash is not really recommended, because FatFs doesn't manage either wear leveling or bad blocks.Thus you may get you flash quickly damaged. So If you don't have any particular constraint for using FatFs I'd suggest the littlefs as a better alternative.

regards

Haithem.

Agreed

If it is done with NOR FLASH (QSPI or whatever) it will also write very slowly.

For a chip down implementation eMMC would be the ticket.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

Shouldn't need to change any FATFS source, just ff_conf.h

I've got confidence in that. I would observe interaction at a sector/block level at the interface in DISKIO

The empty media would need formatting.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
prain
Senior III

I Also recommend you to use littlefs. It has facilities for wear leveling and is fail safe (robust against power loss). littlefs library can be added to your project very easy. You just need 2 files to include.

Also take a look at SPIFFS library.​

I've change sector size in ff_conf.h and reading sector size as 4096 from diskioctl function

#define _MAX_SS 4096 /* 512, 1024, 2048 or 4096 */

as I'm creating both files in 0:/ that's why its assigning same sector no?

shall I create file 1 in 0:/ and file 2 in 1:/ but in this case I'll have to change no of volumes in ff_conf.h?

#define _VOLUMES 1

thanks for your valuable input...will look into littlefs library