# FreeRTOS+FAT ff\_fseek() non-standard behavior

**URL:** <https://forums.freertos.org/t/freertos-fat-ff-fseek-non-standard-behavior/9290>\
**Category:** Libraries\
**Created:** [March 21, 2020, 5:21pm UTC](https://forums.freertos.org/t/freertos-fat-ff-fseek-non-standard-behavior/9290 "2020-03-21T17:21:55Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![carlk3](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/carlk3/32/266_2.png) [@carlk3](https://forums.freertos.org/u/carlk3)\
**Post date:** [March 21, 2020, 5:21pm UTC](https://forums.freertos.org/t/freertos-fat-ff-fseek-non-standard-behavior/9290/1 "2020-03-21T17:21:55Z")

</div>

Re: [ff\_fseek()](https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/stdio_API/ff_fseek.html)

I’m experimenting with large files on SD cards. Writing multi-GB files is slow (on the order of a GB/hour), and I tried speeding it up by using an old Unix trick to reserve the space up front:

```
/* Try to reserve some space */
int rc = ff_fseek( pxFile, 0, FF_SEEK_SET ); // Seek to beginning of file
if (-1 == rc) printf("ff_fseek(%s): %s (%d)\n", pathname, strerror(stdioGET_ERRNO()), -stdioGET_ERRNO());
size_t x = size - 1;
while (x > 0) {
    long y = LONG_MAX - x;
    if (y < 0) {
        rc = ff_fseek( pxFile, LONG_MAX, FF_SEEK_CUR ); // Seek as far as we can
        if (-1 == rc) printf("ff_fseek(%s): %s (%d)\n", pathname, strerror(stdioGET_ERRNO()), -stdioGET_ERRNO());            
        x -= LONG_MAX;
    } else {
        rc = ff_fseek( pxFile, x, FF_SEEK_CUR );
        if (-1 == rc) printf("ff_fseek(%s): %s (%d)\n", pathname, strerror(stdioGET_ERRNO()), -stdioGET_ERRNO());                        
        x = 0;
    }       
}
uint8_t byte = 0;
lItems = ff_fwrite( &byte, sizeof(byte), 1, pxFile );
if (lItems < 1) printf("ff_fwrite(%s): %s (%d)\n", pathname, strerror(stdioGET_ERRNO()), -stdioGET_ERRNO());     

```

However, this fails with

`ff_fseek(/UserSDCrd/bft250M): Illegal seek (-29)`

According to The Open Group Base Specifications, [fseek](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fseek.html#), “The fseek() function shall allow the file-position indicator to be set beyond the end of existing data in the file. If data is later written at this point, subsequent reads of data in the gap shall return bytes with the value 0 until data is actually written into the gap.”

So, the old trick doesn’t work. I think I’m going to have to resort to a special API to reserve space with the SD pre-erase command (ACMD23). According to SD Physical Layer Simplified Specification 6.00 ([https://www.sdcard.org/downloads/pls/index.html](https://www.sdcard.org/downloads/pls/index.html)), “Setting a number of write blocks pre-erased (ACMD23) will make a following Multiple Block Write operation faster compared to the same operation without preceding ACMD23.”

---

<div class="post-metadata">

**Author:** ![carlk3](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/carlk3/32/266_2.png) [@carlk3](https://forums.freertos.org/u/carlk3)\
**Post date:** [March 22, 2020, 4:19am UTC](https://forums.freertos.org/t/freertos-fat-ff-fseek-non-standard-behavior/9290/2 "2020-03-22T04:19:02Z")

</div>

> [@carlk3](#):
>
> “Setting a number of write blocks pre-erased (ACMD23) will make a following Multiple Block Write operation faster compared to the same operation without preceding ACMD23.”

Well, I tried that, and it didn’t help much. I think for it to work, the ACMD23 would have to be followed immediately by all of the CMD25s (WRITE MULTIPLE BLOCK) without any “stop transmission” tokens, but I’m only writing a few blocks at a time through +FAT.

Meanwhile, I discovered [ff\_truncate](https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/stdio_API/ff_truncate.html) which does let me specify the file size. Unfortunately, ff\_truncate does not behave at all like I would expect. The Open Group Base Specifications says “The [_truncate_](https://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html#) () function shall not modify the file offset for any open file descriptions associated with the file.” But [ff\_truncate](https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/stdio_API/ff_truncate.html) seems to permanently move the offset to the end of the file. Even [ff\_rewind](https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/stdio_API/ff_rewind.html) doesn’t seem to get the offset back to the beginning. For example, this little test case:

```
char pcBuffer[8];            
FF_FILE *pxFile = ff_truncate(pathname, sizeof(pcBuffer));
configASSERT(pxFile);
ff_rewind(pxFile); 
size_t i;
for (i = 0; i < sizeof(pcBuffer); ++i) {
    pcBuffer[i] = i;
}
ff_fwrite( pcBuffer, sizeof(pcBuffer), 1, pxFile );
ff_fclose( pxFile );

pxFile = ff_fopen( pathname, "r" );
char val;
while (1 == ff_fread( &val, sizeof(val), 1, pxFile )) {
    printf("%d ", val);
}
printf("\n");

```

produces this output:

`0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7`

and the CLI `dir` command says `[writable file] [size=16]`.

---

<div class="post-metadata">

**Author:** ![htibosch](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/htibosch/32/62_2.png) [@htibosch](https://forums.freertos.org/u/htibosch)\
**Post date:** [March 22, 2020, 6:55am UTC](https://forums.freertos.org/t/freertos-fat-ff-fseek-non-standard-behavior/9290/3 "2020-03-22T06:55:20Z")

</div>

Carl, thanks again for testing and reporting.

The 2 “issues” that you mention are already known:

- `ff_fseek()` pas end-of-file: we decided not to implement this in order to keep the library simple. There has rarely been a request for this.

- Write to a file in append mode: when a file is opened in append mode (like `ff_truncate()` does), and `ff_write()` will always make sure that it writes at the EOF position.

You are right that the behaviour in both cases is not in accordance with the Open Group Base Specifications.

I’m afraid that if we change this now, existing users will complain about the unexpected behaviour.

PS. Doesn’t your device have a 4-bit connection for SD cards?

---

<div class="post-metadata">

**Author:** ![htibosch](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/htibosch/32/62_2.png) [@htibosch](https://forums.freertos.org/u/htibosch)\
**Post date:** [March 22, 2020, 4:56pm UTC](https://forums.freertos.org/t/freertos-fat-ff-fseek-non-standard-behavior/9290/4 "2020-03-22T16:56:21Z")

</div>

In the beginning of this thread, I said that I have never tried FreeRTOS+FAT on a drive larger than 32 GB. I went to a shop and bought a 128 GB Sandisk micro SD-card.

I tested it on a Xilinx Zynq. I had to upgrade the Xilinx driver, because it would only recognise SDHC cards, and not SDXC/UHS-I cards.

You are right, when the low-level driver recognises the large disk, FreeRTOS+FAT has no problem with it.

I created 3 paritions of 42 GB each and mounted them as `/`, `/part1`, and `/part2`.

More tests will be needed before I can really confirm that it works.

---

<div class="post-metadata">

**Author:** ![carlk3](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/carlk3/32/266_2.png) [@carlk3](https://forums.freertos.org/u/carlk3)\
**Post date:** [March 23, 2020, 11:55pm UTC](https://forums.freertos.org/t/freertos-fat-ff-fseek-non-standard-behavior/9290/5 "2020-03-23T23:55:50Z")

</div>

> [@htibosch](#):
>
> Write to a file in append mode: when a file is opened in append mode (like `ff_truncate()` does), and `ff_write()` will always make sure that it writes at the EOF position.

I’m still surprised that I can’t seek back to the beginning. I guess I could close and reopen the file. Anyway, `ff_truncate()` certainly doesn’t save any time.

> [@htibosch](#):
>
> You are right that the behaviour in both cases is not in accordance with the Open Group Base Specifications.
> 
> I’m afraid that if we change this now, existing users will complain about the unexpected behaviour.

Fair enough. I was thinking about portability, since I have been considering porting [SQLite](https://www.sqlite.org/index.html) to FreeRTOS+FAT, but I think it is not too demanding of the filesystem underlying its [virtual file system](https://www.sqlite.org/c3ref/vfs.html) or “VFS”. ([Porting SQLite To New Operating Systems](https://www.sqlite.org/custombuild.html)) (And, it is open source.)

> [@htibosch](#):
>
> PS. Doesn’t your device have a 4-bit connection for SD cards?

It doesn’t have an [SD Host Controller](https://cypresssemiconductorco.github.io/psoc6pdl/pdl_api_reference_manual/html/group __group__ sd__host.html), if that’s what you’re asking. See [PSoC® 6 MCU: PSoC 63 with BLE Datasheet Programmable System-on-Chip (PSoC®)](https://www.cypress.com/documentation/datasheets/psoc-6-mcu-psoc-63-ble-datasheet-programmable-system-chip-psoc).

---

<div class="post-metadata">

**Author:** ![carlk3](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/carlk3/32/266_2.png) [@carlk3](https://forums.freertos.org/u/carlk3)\
**Post date:** [March 24, 2020, 3:53am UTC](https://forums.freertos.org/t/freertos-fat-ff-fseek-non-standard-behavior/9290/6 "2020-03-24T03:53:36Z")

</div>

> [@htibosch](#):
>
> I went to a shop and bought a 128 GB Sandisk micro SD-card.  
> …  
> You are right, when the low-level driver recognises the large disk, FreeRTOS+FAT has no problem with it.

Such a vast amount of space in such a tiny package! And, for not much money, considering.

---

<div class="post-metadata">

**Author:** ![htibosch](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/htibosch/32/62_2.png) [@htibosch](https://forums.freertos.org/u/htibosch)\
**Post date:** [March 24, 2020, 6:57am UTC](https://forums.freertos.org/t/freertos-fat-ff-fseek-non-standard-behavior/9290/7 "2020-03-24T06:57:38Z")

</div>

> Such a vast amount of space in such a tiny package!  
> And, for not much money, considering.

Sure!  
In a meanwhile I tested it further and created a [PR #3](https://github.com/FreeRTOS/Lab-Project-FreeRTOS-FAT/pull/3) on FreeRTOS Labs.

I made sure that you can use these 2 functions:

```c
FF_Error_t FF_Partition( pxDisk, pxParameters );
FF_Error_t FF_Format( pxDisk, xPartitionNumber, xPreferFAT16, xSmallClusters );

```

I found a problem in `FF_Format()` when formatting the second and third partition. That is now repaired in [`ff_format.c`](https://github.com/htibosch/Lab-Project-FreeRTOS-FAT/blob/Zynq_driver_2019.03/ff_format.c)

I was able to use 3 partitions in parallel, each one 42 GB.

---

<div class="post-metadata">

**Author:** ![carlk3](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/carlk3/32/266_2.png) [@carlk3](https://forums.freertos.org/u/carlk3)\
**Post date:** [March 24, 2020, 7:12pm UTC](https://forums.freertos.org/t/freertos-fat-ff-fseek-non-standard-behavior/9290/8 "2020-03-24T19:12:05Z")

</div>

Excellent!

> [@htibosch](#):
>
> … I tested it further and created a [PR #3](https://github.com/FreeRTOS/Lab-Project-FreeRTOS-FAT/pull/3) on FreeRTOS Labs.

I didn’t know until now that FreeRTOS-FAT lived here:  
[FreeRTOS](https://github.com/FreeRTOS)/ **[Lab-Project-FreeRTOS-FAT](https://github.com/FreeRTOS/Lab-Project-FreeRTOS-FAT)**

Earlier, I uploaded a sort of demo project for PSoC 63 to:  
[carlk3](https://github.com/carlk3)/ **[FreeRTOS-FAT-CLI-for-PSoC-63](https://github.com/carlk3/FreeRTOS-FAT-CLI-for-PSoC-63)**
