TSFS File System for Zephyr RTOS

We are happy to announce that the TSFS File System now supports the Zephyr RTOS VFS and native driver interface. While TSFS in itself was able to be easily built and integrated to a Zephyr application before, we now offer a seamless integration to our existing and prospective customers wishing to use or evaluate TSFS within a Zephyr project.

What Does the TSFS File System Bring to Zephyr

TSFS is a transactional, fail safe file system able to achieve and maintain very high performance and reliability on all types of flash storage.

Fail Safety. TSFS can guarantee the integrity of the application’s data in the event of power failures and other unexpected program interruptions. In addition, the transactional nature of TSFS enables application developers to maintain coherency between modifications of multiple files. This could be a firmware upgrade where there is a need to modify more than one file (binary, certificates, configuration files, etc.). TSFS transactions ensure that either all the modifications are committed to non-volatile storage, or, if interrupted, the file system state is brought back to what it was before the beginning of the firmware upgrade if it is interrupted.

Universal flash support. TSFS natively supports NOR, NAND and SDCard/eMMC with consistent features and performance across all media types. On raw flash memories (a.k.a. unmanaged flash) TSFS takes care of wear levelling to maximize the device lifespan. As for NAND flash specifically, TSFS also handles bad block management and ECC (both on-chip or using a dedicated accelerator).

TSFS was designed with modern devices in mind and is compatible with most modern flash memories. This includes recent ECC protected automotive and industrial NOR flash. As for NAND, TSFS can use both parallel SLC NAND as well as serial NAND flash. Finally, TSFS can leverage multiplane and multidie chips for improved performance.

High performance and efficiency. TSFS aims to extract maximum performance out of each media type within a strict RAM and CPU usage budget. Typical RAM usage is around 12 KiB on most media type and configuration. Meanwhile, TSFS can maximize both random and sequential file operations and maintain bounded real-time latency across file system operations. More details on TSFS performance can be found in our article comparing four popular embedded file systems.

Zephyr Integration Features

TSFS can leverage many features of Zephyr to help a seamless transition to a new file system for application developers used to develop on Zephyr.

Build Integration

TSFS for Zephyr is distributed as an external module which can be integrated easily with an existing project. All that is needed is to include the TSFS source directory to the CMAKE EXTRA_ZEPHYR_MODULES variable. Compile-time configurations are also integrated into Kconfig for easier build management.

VFS Integration

The main feature of the TSFS integration is the support for the Zephyr VFS. The VFS enables multiple different file systems to coexist under a unified API and path structure. User wishing to use TSFS in their Zephyr application can register a new file system of type FS_TSFS as an out-of-tree file system with the fs_register() API and then define a mount point using the usual fs_mount_t structure and a call to fs_mount().

rtn = fs_mount(&mntp);

To support high reliability applications, TSFS also defines additional error codes to be returned by the VFS API through a user configurable numerical offset. This enables returning the FS_TSFS_ERROR_CORRUPT error code when the underlying file system is damaged or corrupted and FS_TSFS_ERROR_FATAL if the TSFS source code encounters an assertion failure during operation.

Existing users, or those who require a more fine-grained usage of the TSFS API, such as the transactions commit operation, always have the option to use the native TSFS API directly if they wish.

Storage Drivers Integration

Through the Zephyr flash or disk interfaces, TSFS is able to use existing NOR and SD Card/eMMC controllers and media drivers available with the Zephyr distribution. Application developers can thus leverage the considerable platform support of the Zephyr ecosystem with TSFS.

A Word About NAND Support

TSFS also supports NAND flash memories, both serial (QSPI) and parallel devices. This enables system designers to considerably reduce cost and increase performances when transitioning from large 32MiB+ NOR Flash. NAND flash also has considerable advantages over costly eMMC devices with lower cost, better real-time performances and reduced power usage.

Integration Tests

To ensure that everything is properly integrated, the distribution of TSFS for Zephyr includes a set of integration tests to validate functionality and performance as well as help troubleshooting.

How to Add TSFS to your Zephyr Project

The first step is to add TSFS source to the build. This can be achieved by adding the following line to the top level CMakeList.txt.

set(EXTRA_ZEPHYR_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../tsfs")

Then, before using the file system, one must create and initialize a TSFS instance. For example, on a 128MiB MT25Q devices the initialization would look like this:

rtn = tsfs_init(&g_mem_seg);
APP_ASSERT(rtn == RTNC_SUCCESS);

rtn = tsfs_media_zephyr_flash_create("tsfs_media", 
    DEVICE_DT_GET(DT_NODELABEL(mt25ql512ab1)), &g_mem_seg);
APP_ASSERT(rtn == RTNC_SUCCESS);

fs_cfg.write_buffer_size = 4096U;
fs_cfg.read_buffer_size = 4096u;
fs_cfg.aux_buffer_size = 4096u;
fs_cfg.buffer_alignment = 128u;
fs_cfg.lookup_cache_size = 1024u;
fs_cfg.max_cached_file_count = 10u;
fs_cfg.max_fs_size = 128ull*1024*1024;
fs_cfg.max_opened_file_count = 10u;
fs_cfg.max_update_extent_count = 128u;
fs_cfg.min_sec_size = 4096u;
fs_cfg.p_aux_buffer = NULL;
fs_cfg.p_read_buffer = NULL;
fs_cfg.p_write_buffer = NULL;
rtn = tsfs_create("/tsfs", &g_mem_seg, &fs_cfg);
APP_ASSERT(rtn == RTNC_SUCCESS);

The media can then be formatted to the TSFS format if it is not already.

tsfs_params_t fs_params;

fs_params.sector_size = 4096u;
fs_params.update_extent_count = 128u;
rtn = tsfs_format("tsfs_media", &g_mem_seg, &fs_params);
APP_ASSERT(rtn == RTNC_SUCCESS);

And finally the newly created instance needs to be mounted, in this example under the /tsfs mount point:

memset(&mntp, 0, sizeof(mntp));
mntp.type = FS_TSFS;
mntp.mnt_point = "/tsfs";
mntp.storage_dev = (void *)"tsfs_media";
rtn = fs_mount(&mntp);
APP_ASSERT(rtn == RTNC_SUCCESS);

To validate that everything is working properly you can run the integration test at this point.

rtn = zephyr_fs_integration_test(&mntp);
APP_ASSERT(rtn == RTNC_SUCCESS);

Parting Words

If you need a robust high performance file system for your Zephyr application make sure to visit the TSFS page. You can also download the user manual. Feel free to contact us to discuss your next embedded software project!


See all articles