Hi All,
I am using FlashFS (MDK-ARM V4.22) with an SPI FLASH (Atmel AT45DB321C) and STM32F207.
My problem is that when I delete files using fdelete() the free space (as reported by ffree()) is _never_ recovered, even though the files disappear from the file list (as reported using repeated calls to finfo()). I can delete ALL the files, and NONE of the space is recovered.
I realise that the FLASH can only be erased a block at a time, and indeed the manual says:
"When the file content is modified, the old file content is invalidated and a new memory block is allocated. The Flash Block is erased when all the data stored in the Flash Block have been invalidated."
This is perfectly reasonable. However, this reclamation of space when an entire block is invalidated never seems to happen; ffree() only ever reports a decreasing amount of free space, and I never hit the breakpoint I set on the SPI driver EraseSector() function.
The only way to recover the space seems to be to call fformat() which, as expected, erases the whole FLASH.
Does anyone have any ideas as to what I might be doing wrong?
Thanks in advance,
Christopher Hicks ==
But what happens if you try to fill the memory card again?
Maybe the erase isn't performed until there is a pressure to get access to more sectors?
Thanks, Per. I wondered about that, too.
In this case any file I try to write to the FLASH gets truncated at the length that was reported by ffree() immediatley preceding the write, and afterwards ffree() reports zero. EraseSector() in the SPI driver never gets called.
For example, suppose a freshly formatted FLASH has 4MBytes free space, and then we do the following sequence:
1) Write file1, size 1.5MByte. This succeeds and now ffree() reports 2.5MByte free.
2) Write file2, size 1.5MByte. This succeeds and now ffree() reports 1MByte free.
3) Delete file1. This succeeds, and now ffree() still reports 1MByte free.
4) Delete file2. This succeeds, and now ffree() still reports 1MByte free.
At this point, finfo() reports no files on the FLASH, and ffree() reports 1MByte free space.
5) Attempt to write file4, size 1.5MByte. This write fails at around the 1MByte mark. finfo() shows the existence of file4, and I can read its contents correctly as far as it goes. ffree() reports 0 Bytes free. The only way to recover space seems to be fformat().
It really does appear as if the filesystem is not doing its garbage collection for some reason. I am currently doing some tests to see whether the RAM drive behaves the same or differently. I should add that in all other respects the filesystem seems to work perfectly.
> I am currently doing some tests to see whether the RAM drive behaves the same or differently.
It appears that the RAM drive reclaims space as expected.
CH ==
Did you implement the EraseSector() function in your flash driver? Is it working correctly?
If this function fails or is not implemented, no space is reclaimed after fdelete.
Yes, I believe EraseSector() does work.
I put a breakpoint on my EraseSector() implementation (well, actually the implementation supplied by Keil as an example driver for the Atmel SPI FLASH). EraseSector() is called during fformat() (many times, of course) but EraseSector() does NOT seem to be called at any other time.
Because fformat() works correctly, I deduce that EraseSector() is doing its job. I do not have EraseChip() implemented as the manual states that this is optional.
What about the sector protection? Did you by chance protect (in software or hardware) a sector program and erase?
Thank you - that's a good point. It has also occurred to me to check whether the device might be configured for 512 byte sectors instead of the default 528. Will check both.
I have also dug into the datasheet for the part and the Keil driver code a little more. I discover that the ProgramPage() driver function uses a command (0x83) to the FLASH that automatically does an erase before programming. Perhaps this is why EraseSector() is not used except during formatting.
> Thank you - that's a good point. It has also occurred to me to check whether the device > might be configured for 512 byte sectors instead of the default 528. Will check both.
Have checked and all is in order here.
I have tried calling the FLASH driver functions directly with toy code:
uint8_t tmpbuf[2000]; [...] Init(0,0); ReadData(1234, 2000, tmpbuf); for (int i=0; i<2000; i++) { tmpbuf[i] = tmpbuf[i] + i; } ProgramPage(1234, 1000, tmpbuf); ReadData(1234, 2000, tmpbuf); for (int i=0; i<2000; i++) { tmpbuf[i] = tmpbuf[i] + 1; } ProgramPage(1234+500, 1000, tmpbuf+500); ReadData(1234, 2000, tmpbuf); EraseSector (1234); ReadData(1234, 2000, tmpbuf);
Stepping through carefully, examining the contents of tmpbuf in a (non-cached!) memory window shows everything apparently working correctly.
I am now guessing that the library's use of the program command 0x83 that includes an erase (instead of calling EraseSector() explicitly) has the unanticipated side-effect of causing sectors never to be marked copmpletely invalid, erased, and added to the free list. However, this is in library code to which I do not have source, so I can't verify this.
I'm a bit confused by this lack of source code, though, as I found a bug in FlashFS once before that was fixed by Keil (<http://www.keil.com/forum/14006/#msg69836>). Has poilcy about distributing source for FlashFS changed in the last three years, or am I just not looking in the right place?
It occurs to me to mention one other thing. My implementation of the low-level SPI function SendBuf(U8 *buf, U32 sz) (which actually transmits data to the FLASH chip over SPI) overwrites buf.
The protoype supplied by Keil does not specify that buf is const, so I assume I am allowed to do this. I cannot be certain, but I think the problem with the free space not being recovered pre-dates this change I made to the implementation of SendBuf() anyway.
> My implementation of the low-level SPI function SendBuf(U8 *buf, U32 sz) (which actually > transmits data to the FLASH chip over SPI) overwrites buf.
This was the problem. Keil documentation and code ask for my implentation of
BOOL SendBuf(U8 *buf, U32 n);
but actually needs
BOOL SendBuf(const U8 *buf, U32 n);
in order for the filesystem to work properly. Have reported this as a bug to Keil/ARM.
=> Has poilcy about distributing source for FlashFS changed in the last three years, or am I just not looking in the right place?
Policy changed.
http://www.keil.com/forum/18662/ http://www.keil.com/forum/18702/
Danny Curran, 27-Apr-2011 16:16 GMT ----------------------------------- NDA signed and returned was given a link to a zip file and downloaded it. About approx 12 new files and 4 or so changed in the Flash FS Not looked a the USB side but can see differances there as well.