This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Getting SL_FS_ERR_OFFSET_OUT_OF_RANGE error when writing to SFlash file

Expert 1570 points
Other Parts Discussed in Thread: CC3200, CC3200SDK, UNIFLASH

I'm using the SimpleLink sl_FsOpen function on a CC3200 device to create and write to SFlash files, as demonstrated in the file operations example project, but am getting an error when writing beyond ~36400 bytes.  The device has a 16MB Flash chip connected.

I'm using a call like this:

            lRetVal = sl_FsOpen((_u8 *)pFile->deviceFileName,
                                 FS_MODE_OPEN_CREATE(pFile->maxFileSize, _FS_FILE_OPEN_FLAG_COMMIT|_FS_FILE_PUBLIC_WRITE|_FS_FILE_PUBLIC_READ),
                                 (_u32 *)&pFile->ulToken,
                                 (_i32 *)&pFile->dataFileHandle);

where the maxFileSize argument is 2000x3584 (I read in another thread that the file size should be a multiple of 3584) which works out to about 7MB, but I've also tried it with the maxFileSize = 20x3584 (~70kB).  In either case, if I try to write to the file using sl_FsWrite past ~36400 bytes I get error -15 (SL_FS_ERR_OFFSET_OUT_OF_RANGE).  What could be causing this?

  • Hi,

    This should be possible. First please call sl_FsDel on this file to delete the file and then try to open the file. There might a file with the same name existing in the file system with smaller size.

    Regards,
    Raghavendra
  • I reformatted the Flash and it now lets me write past that point.  (I thought I had it formatted larger before, but perhaps not.)

    But I get an error -30 (SL_FS_ERR_NO_AVAILABLE_BLOCKS) if I try to do this with a file about 7MB in size, even though the Flash is 16MB.  Why would that be?

    So I reduced the size to ~5MB and it doesn't give that error.  Is it normal to take several seconds to create a new file ~5MB in size?

    How should I check if the file has already been created to avoid creating it again?  Shouldn't using FS_MODE_OPEN_CREATE cause it to only open the file if it was already created?  It doesn't seem to do that.

    Where is the best source of documentation for this library?  I have seen this file:///C:/TI/CC3200SDK_1.1.0/cc3200-sdk/docs/simplelink_api/html/group___file_system.html but it doesn't explain things very well.

    Thanks

  • Hi,

    As mentioned in the release notes, you cannot open a file with a size larger than 1MB. "File size is limited to 1MByte (No error will be returned while trying to create a larger size)".

    If you try to create a file that already exists, it would just go and open it. Just try to do a sl_FsGetInfo before opening the file it would return the error code 'SL_FS_ERR_FILE_NOT_EXISTS' if the file does not exist.

    Regards,
    Raghavendra
  • Wow. I didn't notice that. In the 1.0.0 SDK release notes it says there is no file size limit. So did this change for SDK 1.1.0, or was it the case in 1.0.0 also?
    Why is there this limitation, and when is it expected to be fixed?
  • Hi,

    Let me answer your queries:

    • 1MB file is the limitation per file. This is the case regardless of the flash capacity. The root cause is implementation of the file system in the device and hence is not related to SDK
    • the 3584 size is 512 bytes less than a block sie of 4KB. This is the header per file. To save as much memory on the flash as possible, it is recommended to reserve this 512 bytes per file. So the file should not be a multiple of 3584. For example, if you open a file with 5*4096 than 6 blocks would be allocated on the file system. If you open it with 5*4096 - 512, only 5 blocks would be allocated
    • SL_FS_ERR_NO_AVAILABLE_BLOCKS means the flash is occupied
    • FS_MODE_OPEN_WRITE is used only for openning of existing files. FS_MODE_OPEN_CREATE invokes _sl_GetCreateFsMode() which invokes _FS_MODE() which uses _FS_MODE_OPEN_WRITE_CREATE_IF_NOT_EXIST. So it either creates the file or opens it to write

    Please let me know if you have further questions.

    Shlomi

  • Thanks Shlomi,

    My understanding was the 512 bytes was for the entire file also, but then I saw this in the Simplelink Programmer's Guide: (from the SDK Simplelink docs folder file:///C:/TI/CC3200SDK_1.1.0/cc3200-sdk/docs/simplelink_api/html/group___file_system.html#ga6df7dfcefa195a2bc5ef81dbbcaab5ed)

    "For optimal FS size, use max size in 4K-512 bytes steps (e.g. 3584,7680,117760)"

    [Edit] Sorry, I read "4k-512 bytes steps" as "3584 byte steps", but didn't check the math on the example file sizes provided, which now confuse me further.  7680 = 2 X 4096 - 512, but 117760 = 29 * 4096 - 1024.

    A few more things I wanted to confirm:

    1. In the case of using FS_MODE_OPEN_CREATE, if the file wasn't already created, is the file also opened?  I see in the example project that after calling this, the file is then closed and opened again for writing.  Does this have to happen, or can we not start writing after using FS_MODE_OPEN_CREATE?

    2. I assume creating the file is a permanent action so on each reset this does not need to be done again, however if it is called again after the file was already created and written to, the contents are preserved (i.e. it does not erase the file and create it again).  Or should I check if the file exists and only create it if it doesn't?

    3. Once the file size is specified on calling sl_FsOpen with FS_MODE_OPEN_CREATE, the max file size doesn't change, correct?  I.e. on subsequent calls to sl_FsOpen the originally specified file size still applies, and the max file size can't be changed without deleting and creating the file again?

         Also, is the 1MB file size limitation expected to be fixed?  We are trying to save a lot of sensor data to SFlash so right now I'm working on revising the firmware to handle multiple smaller files to work around this limitation.  We have integrated an SD card but I had to go back to using SFlash because the FatFS library was giving me a lot of problems with locking up the system.  So currently it seems the CC3200 is not viable for storing large amounts of data, which is very frustrating.

         [Update] If I create a file with size of 1024x1024-512 (=1048064 bytes) and then call getinfo, it gives AllocatedLen of only 3656 bytes.  Maybe I misunderstood the 1MB file limit - I took it to mean 1MiB, but I suppose it's actually 1MB (1000000).  So I created a new file with size 1000000 bytes, and then calling getinfo returns 1007176 for allocated size.  Using 250000 allocates 253512.  What's going on here?  I'm using getinfo to check the file size to make sure it's the right size and if not delete and recreate the file.  But how can I predict what size will be allocated to a file for a given max file size specified when creating it, and how can I be sure it won't change?
        

    Regards,

    Angelo

  • Angelo,

    Please see my responses.

    1. In the case of using FS_MODE_OPEN_CREATE, if the file wasn't already created, is the file also opened?  I see in the example project that after calling this, the file is then closed and opened again for writing.  Does this have to happen, or can we not start writing after using FS_MODE_OPEN_CREATE?

    [Shlomi] using FS_MODE_OPEN_CREATE will create the file if it does not exist. You can write to it and then close it. No need to open->close and then open again for writing.

    2. I assume creating the file is a permanent action so on each reset this does not need to be done again, however if it is called again after the file was already created and written to, the contents are preserved (i.e. it does not erase the file and create it again).  Or should I check if the file exists and only create it if it doesn't?

    [Shlomi] using FS_MODE_OPEN_CREATE to open and then just close without any writing, erases the entire file. Erasing happens on openning the file.

    3. Once the file size is specified on calling sl_FsOpen with FS_MODE_OPEN_CREATE, the max file size doesn't change, correct?  I.e. on subsequent calls to sl_FsOpen the originally specified file size still applies, and the max file size can't be changed without deleting and creating the file again?

    [Shlomi] correct

    Regarding your size conflicts, you need a deeper understanding of how the device actually allocate size on flash.

    It is a multi stage procedure involving pages and blocks.

    1. calculate page size
      1. file up to 64KB -> page is 256 bytes
      2. from 64KB-256KB -> page is 1024 bytes
      3. above 256KB -> page is 4096 bytes
    2. round up to nearest page
    3. add header of 440 bytes and round up to nearest block (4096 bytes)
    4. actual size reported by sl_FsGetInfo is the true size on flash minus the 440 header

    For your 3 examples:

    File size

    Page size

    Round to page

    Add header and round to block

    Allocated size via sl_FsGetInfo()

    250000

    1024

    250880

    (245 pages)

    253952

    (62 blocks)

    253512

    1000000

    4096

    1003520

    (245 pages)

    1007616

    (246 blocks)

    10007176

    1048064

    4096

    1048576

    (256 pages)

    1052672

    (257 blocks)

    3656

    Shlomi

     

     

  • Thank you for clarifying Shlomi. What is the best source of documentation on this?
  • Hi,

    File system documentation can be found on the Programmer's guide but it does not explain in details the calculations.

    We need to add similar calculation to the Programmer's guide.

    You can also look into Uniflash user guide. Just added a chapter explaining on file system

    http://processors.wiki.ti.com/index.php/CC31xx_%26_CC32xx_UniFlash#Serial_Flash_usage_and_design

    Shlomi

  • Is there a way, after writing to a file, to erase the contents without deleting and recreating the entire file? How is the FileLen member of SlFsFileInfo_t determined? Is it just the highest offset written to in the file? I would like make that read zero after working on the file so after reset the next process will start at the beginning of the file.
  • Also, I'm seeing in some cases the GetInfo call reports a non-zero file size after writing some data and resetting, but when reading the file everything is 0xFF. What would cause this. It's possible the file wasn't closed after writing before resetting, but then would the file size have changed? Would this sequence cause it: open, write, close, open, write, reset ?
  • Hi,

    If you open->write and then reset before closing probably the file, you should get an error code when trying to open the same file again.

    The error is SL_FS_FILE_HAS_NOT_BEEN_CLOSE_CORRECTLY.

    Shlomi

  • Hi Shlomi,
    I have seen that error, but usually I don't get that after opening and writing to a file, and resetting without closing again. Typically I would just get a return code of 0, and the filelen parameter is 0, which is OK. But I've seen cases where the filelen is non-zero but the data in the file is mostly 0xFF. I have tried various things to try to reproduce this to understand why it would happen, but haven't been able to.

    So I'm faced with scanning through the contents of the file to check its validity if I can't ensure the contents are not corrupt. It also brings me back to my previous questions - Is there a way, after writing to a file, to erase the contents without deleting and recreating the entire file? How is the FileLen member of SlFsFileInfo_t determined? Is it just the highest offset written to in the file?

    Angelo
  • Hi Angelo,

    What you need to understand is that flash devices need to be erased (i.e. all 0xff) before you can write to them. So the device actually does that when openning the file for write. So if you just open (for write) and than close it, you will get a 0 length on the FileLen. The content is not relevant (actually I tried it myself and since the file is 0 length, the content is not all 0xff but not defined).

    Any case, FileLen indicates the highest offset you have been written to. The is correct.

    Regarding the 0xff you saw on some cases, it can only be explained by writing to an offset (not to the entire file) and than close it. In this case, all untouched offsets would have all 0xff since the device erased it prior to writing.

    So you can implement "erase the contents without deleting and recreating the entire file" if you open the file and than write to the highest allocated offset 0xff.

    Tried it myself and it works.

    Shlomi

  • Thank you for your explanation. So do I understand correctly that if I open a file for writing (after previously writing to it), all previous contents are erased? That's troublesome. I understand Flash memory needs to be erased before being written to, but I thought Simplelink was managing this somehow so the file could be accessed more like a typical file on a hard drive or SD card, etc.

    So in that case I have to consider files as write once only, i.e. that I can't come back and append new data to an existing file, is that right?
  • Your understanding is correct. There is no easy option to append to an existing file.

    This is not like a usual file on hard drive. The main reason is that the SimpleLink device does not have enough RAM memory resources to store a content of an entire file to allow managing simple read-modify-write method. It originally designed for device usage only and then also offered to user usage.

    If you leave the file open, you can write to whatever offset you like (without writing to the same offset again). You can implement read-modify-write using your host MCU (if you have enough resources for that).

    Shlomi

  • OK thanks a lot Shlomi, this helps me understand the behaviour I've been getting and also how to implement the library for this application.
  • Sure, no problems. I am closing this thread.
  • Shlomi, I tried writing 0xFF to the highest offset (just one byte to the offset equal to FsFileInfo.FileLen) but then when I check GetInfo again the FileLen just increases by 1. I get a return value from the sl_FsWrite call of 1, and then I close the file which gives no errors. I also tried writing to the offset of (FsFileInfo.FileLen - 1), and the file size doesn't change, but doesn't go to zero either.

    Am I doing something wrong?
  • It is expected behavior unless I misunderstood you.

    After writing X bytes to an allocated size Y (where Y > X), FileLen should show X.

    If you write to offset (X - 1) which is the last written byte, the length remains the same.

    The content would be all 0xFF if you read the file.

    So it is like the file has been erased but of course it exists (as you have not derased it).

    Erasing it from the file system would need to go through the erase API.

  • OK, got you, I guess I wasn't clear enough, I'm concerned about the FileLen parameter - I want that to return to zero. I thought that's what you were suggesting would happen by writing to the last offset.

    What I'm trying to do is: after reset get the file info on some data files, including FileLen. If FileLen is non-zero I would assume there is data in there (saved previously before getting reset or powered down) and then process it. But if that file was already processed previously before being reset, I would like the filelen to show zero so I don't process it again. It seems I should be able to do this by deleting the file and creating it again, but this takes several seconds and I'm looking to do this all rather quickly. So I wanted to just somehow mark that the file can be considered empty and written to again, even if there are still old data in it.
  • Well, I think that if you open and close immediatelly all data is gone and the FileLen is 0. However, the time it takes to open the file would still be high depending on its size. It sounds as if you need to manage it on the host MCU as it depends on what exactly you refer by "processed file".