SEGGER emFile for ModusToolbox

July 17, 2026 · View on GitHub

Overview

emFile is a fail-safe filesystem designed for embedded systems by SEGGER Microcontroller GmbH that can be used with different types of storage devices. It is a high-performance library optimized for high speed, versatility, and a minimal memory footprint of both RAM and Flash.

Infineon has licensed emFile from SEGGER and offers it for free to its customers. This middleware library provides emFile in the form of pre-built libraries and supports FAT 12/16/32 file systems.

Important Notice Regarding Long File Names (LFN): If you configure the software to support long file names on FAT file systems, you should determine whether a license from Microsoft is required. Infineon Technologies AG and its suppliers grant no license under Microsoft's intellectual property rights and assume no liability for any use of the software without obtaining any license that may be required.

Features

  • SEGGER emFile library v5.22.0

  • Supports FAT 12/16 and FAT 32 file systems

    • COMPONENT EMFILE_FAT16 supports FAT12 and FAT 16

    • COMPONENT EMFILE_FAT32 extends FAT12/16 and supports functionality FAT 32

  • Supports Long File Name (LFN)

  • Cache support via RAM for optimized performance

  • Supports fail-safety through the Journaling component

  • Supports encryption: DES (56-bit key length)

  • Supports thread safety for use with multi-threaded RTOS environments using the abstraction-rtos library

  • Supports memory card devices such as MMC, SD, SDHC, and eMMC using SD bus mode (card mode)

    • The SD/MMC HW layer uses DMA and waits on a semaphore until data transfer completes when enabled

    • The SD/MMC driver supports up to 2 instances (FS_MMC_NUM_UNITS=2)

  • Supports Single-SPI/Dual-DSPI/Quad-SPI based NOR flash memories

  • Supports wear leveling for use with NOR flash memories

When to Use

Use emFile when your embedded application needs a reliable, high-performance FAT file system on non-volatile storage. Typical use cases include:

  • Data logging - Storing sensor readings or diagnostic data on an SD card or NOR flash for later retrieval.
  • Firmware update storage - Saving firmware images to an external storage medium and applying them at runtime.
  • Configuration file management - Reading and writing application settings stored as files on a FAT-formatted device.
  • File exchange with host systems - Creating or reading files on a storage device that must also be accessible from a PC or other host (for example, over USB mass storage).
  • Multi-threaded (RTOS) applications - When thread-safe file system access is required across multiple concurrent tasks.

emFile is appropriate when FAT 12/16/32 compatibility, wear leveling on NOR flash, or fail-safe operation with journaling support is required.

Prerequisites

  • ModusToolbox™ software v3.6 or later with Project Creator, Library Manager, and Device Configurator
  • Toolchain: GCC ARM (included with ModusToolbox) or ARM Compiler 6
  • Hardware: PSoC(TM) Edge E84 MCU development board
    • SD card example: board with SDHC peripheral and a micro SD card
    • NOR flash example: board with SMIF/QSPI peripheral
  • Serial terminal (for example, PuTTY or Tera Term) configured to 115200 baud, 8N1

How to Use

Quick Start

The Quick Start examples below are provided for PSoC(TM) Edge E84 MCUs. They demonstrate initializing the file system on the target memory, creating and opening a file, and updating its content.

Project Creation

  1. Create an empty application using the Project Creator tool in ModusToolbox™ software.
  2. Add the emfile and retarget-io libraries using the Library Manager.
  3. To run the example in an RTOS environment, add the FreeRTOS library using the Library Manager. Then add RTOS_AWARE and FREERTOS to the COMPONENTS variable in the Makefile:
    COMPONENTS += RTOS_AWARE FREERTOS
    
    Note: In the RTOS environment, select Active mode for System Idle Power Mode in the Power personality (System Tab) in the Device Configurator.
  4. (NOR flash driver only) To use the same storage for code execution and file system, perform the additional steps described in the XIP Support section below.

HW Configuration in Device Configurator

All HW resources used in this Quick Start must be configured in the Device Configurator:

  • UART for logging
  • One pin to check the button status
  • Memory Card Device HW – SDHC
  • NOR flash HW – SMIF

If a different alias name is selected instead of the expected resource name in the Device Configurator, the code snippets must be updated accordingly.

ResourceExpected name
Quad Serial Memory InterfaceSMIF_EMFILE
SD Host ControllerSDHC_EMFILE
Serial Communication Block (for debug UART)DEBUG_UART
PinCYBSP_USER_BTN

Recommended Memory Card Device configuration

Recommended Memory Card Device configuration

Note: The pin assignments below are board-specific. Select appropriate pins based on your board documentation.

SD Host Controller (SDHC) 1 (SDHC_EMFILE) - Parameters

CategoryParameterValue
OverviewConfiguration HelpOpen SD Host Documentation
TimingClock8 bit Divider 0 clk [USED]
TimingInput Clock Frequency (kHz)100000.000
GeneralCard TypeSD/SDIO
GeneralDMA TypeADMA2
GeneralLED ControlDisabled
GeneralBus Width4-bit
GeneralEnable Low Voltage SignalingDisabled
InputsCLKP7[1] digital_inout (CYBSP_SDHC_CLK) [USED]
InputsCMDP7[0] digital_inout (CYBSP_SDHC_CMD) [USED]
InputsDAT0P7[3] digital_inout (CYBSP_SDHC_IO0) [USED]
InputsDAT1P7[5] digital_inout (CYBSP_SDHC_IO1) [USED]
InputsDAT2P7[6] digital_inout (CYBSP_SDHC_IO2) [USED]
InputsDAT3P7[7] digital_inout (CYBSP_SDHC_IO3) [USED]
InputsCard DetectUnassigned
InputsCard Mechanical Write ProtectUnassigned
InputsCard if Power EnabledUnassigned
InputsIO Volt SelectUnassigned
AdvancedStore Config in FlashEnabled

Recommended SMIF configuration

Recommended SMIF configuration

Note: The pin assignments below are board-specific. Select appropriate pins based on your board documentation.

Quad Serial Memory Interface (QSPI) 0 (SMIF_EMFILE) - Parameters

CategoryParameterValue
ClocksInterface Clock SourceCLK_HF3 root_clk [USED]
ClocksUse internal DLLDisabled
ClocksInterface Clock Frequency99 MHz
ClocksRX Capture ModeNormal SPI SDR/DDR
SystemSMIF IP Version6
Data LinesSPI Data[0]P1[0] / SMIF0_SPIHB_DATA0 aux (CYBSP_QSPI_D0) [USED]
Data LinesSPI Data[1]P1[1] / SMIF0_SPIHB_DATA1 aux (CYBSP_QSPI_D1) [USED]
Data LinesSPI Data[2]P1[2] / SMIF0_SPIHB_DATA2 aux (CYBSP_QSPI_D2) [USED]
Data LinesSPI Data[3]P1[3] / SMIF0_SPIHB_DATA3 aux (CYBSP_QSPI_D3) [USED]
Data LinesSPI Data[4]Unassigned
Data LinesSPI Data[5]Unassigned
Data LinesSPI Data[6]Unassigned
Data LinesSPI Data[7]Unassigned
Slave SelectSPI Slave Select 0Unassigned
Slave SelectSPI Slave Select 1P2[0] digital_out (CYBSP_QSPI_SS) [USED]
Slave SelectSPI Slave Select 2Unassigned
Slave SelectSPI Slave Select 3Unassigned
DMA TriggersRX Trigger OutputUnassigned
DMA TriggersTX Trigger OutputUnassigned
InterruptMemory Mode Alignment ErrorDisabled
InterruptRX Data FIFO UnderflowDisabled
InterruptTX Command FIFO OverflowDisabled
InterruptTX Data FIFO OverflowDisabled
AdvancedStore Config in FlashEnabled

Recommended Debug UART configuration

Recommended Debug UART configuration (part 1)

Recommended Debug UART configuration (part 2)

Note: The pin assignments below are board-specific. Select appropriate pins based on your board documentation.

Serial Communication Block (SCB) 2 (DEBUG_UART) - Parameters

CategoryParameterValue
GeneralCom ModeStandard
GeneralBaud Rate (bps)115200
GeneralOversample8
GeneralBit OrderLSB First
GeneralData Width8 bits
GeneralParityNone
GeneralStop Bits1 bit
GeneralEnable Digital FilterDisabled
Enable RS-485TX-EnableDisabled
Flow ControlEnable Flow ControlDisabled
Flow ControlCTS PolarityActive Low
Flow ControlRTS PolarityActive Low
Flow ControlRTS Activation Level63
ConnectionsClock16 bit Divider 0 clk [USED]
ConnectionsRXP6[5] digital_inout (CYBSP_DEBUG_UART_RX) [USED]
ConnectionsTXP6[7] digital_inout (CYBSP_DEBUG_UART_TX) [USED]
ConnectionsRX Trigger OutputUnassigned
ConnectionsTX Trigger OutputUnassigned
Trigger LevelRX FIFO Level63
Trigger LevelTX FIFO Level63
Multi Processor ModeEnable Multi Processor ModeDisabled
Multi Processor ModeAddress0
Multi Processor ModeMask255
Multi Processor ModeAccept Matching Address in RX FIFODisabled
AdvancedDrop on Frame ErrorDisabled
AdvancedDrop on Parity ErrorDisabled
AdvancedBreak Signal Bits11
AdvancedBreak LevelLow Level Pulse Detection
AdvancedStore Config in FlashEnabled
API ModeAPI ModeHigh Level

Recommended Button Pin configuration

Recommended Button Pin configuration

Note: The pin assignments below are board-specific. Select appropriate pins based on your board documentation.

P8[3] (CYBSP_SW2, CYBSP_USER_BTN1, CYBSP_USER_BTN) - Parameters

CategoryParameterValue
OverviewConfiguration HelpOpen GPIO Documentation
GeneralDrive ModeResistive Pull-Up, Input buffer on
GeneralInitial Drive StateHigh (1)
GeneralSecure attributeNon-secure access (1)
InputThresholdCMOS
InputInterrupt Trigger TypeNone
OutputSlew RateFast
OutputExtended Drive StrengthDisabled
OutputDrive Strength1/2
Internal ConnectionDigital OutputUnassigned
Internal ConnectionDigital InOutUnassigned
Internal ConnectionAUXUnassigned
AdvancedStore Config in FlashEnabled

Add emFile Logic to main.c

Specific steps for NOR flash (SPI flash) driver configuration

  1. Include the required headers:
    #include "mtb_hal_memoryspi.h"
    #include "cy_sysint.h"
    #include "cy_smif.h"
    
  2. Add global variables:
    static mtb_hal_memoryspi_t * memspi_obj_ptr;
    static cy_stc_smif_context_t memspi_context;
    
  3. Add the interrupt handler for NOR flash HW:
    void nor_isr(void)
    {
        mtb_hal_memoryspi_process_interrupt(memspi_obj_ptr);
    }
    
  4. Add the function for NOR flash HW initialization:
    void FS_NOR_HW_SPIFI_ConfigureHw(mtb_hal_memoryspi_t * memspi_obj)
    {
        cy_rslt_t hal_status;
        cy_en_smif_status_t pdl_smif_status;
        cy_en_sysint_status_t pdl_sysint_status;
    
        memspi_obj_ptr = memspi_obj;
    
        pdl_smif_status = Cy_SMIF_Init(SMIF_EMFILE_HW, SMIF_EMFILE_hal_config.config, 10000UL, &memspi_context);
        if (CY_RSLT_SUCCESS != pdl_smif_status)
        {
            printf("Cy_SMIF_Init returns error status\n\r");
            CY_ASSERT(0U);
        }
    
        hal_status = mtb_hal_memoryspi_setup(memspi_obj_ptr, &SMIF_EMFILE_hal_config, &memspi_context);
        if (CY_RSLT_SUCCESS != hal_status)
        {
            printf("mtb_hal_memoryspi_setup returns error status\n\r");
            CY_ASSERT(0U);
        }
    
        cy_stc_sysint_t nor_isr_config =
        {
            .intrSrc = SMIF_EMFILE_IRQ,
            .intrPriority = 3U
        };
    
        pdl_sysint_status = Cy_SysInt_Init(&nor_isr_config, nor_isr);
        if (CY_SYSINT_SUCCESS != pdl_sysint_status)
        {
            printf("Cy_SysInt_Init returns error status\n\r");
            CY_ASSERT(0U);
        }
    
        NVIC_EnableIRQ((IRQn_Type) nor_isr_config.intrSrc);
    
        Cy_SMIF_SetDataSelect(SMIF_EMFILE_HW, (memspi_obj_ptr->chip_select), CY_SMIF_DATA_SEL0);
        Cy_SMIF_Enable(SMIF_EMFILE_HW, memspi_obj_ptr->context);
    }
    
  5. Add EMFILE_NOR_FLASH to the COMPONENTS variable in the Makefile:
    COMPONENTS += EMFILE_NOR_FLASH
    

Specific steps for Memory Card Device (SD/MMC) driver configuration

  1. Include the required headers:
    #include "mtb_hal_sdhc.h"
    #include "cy_sd_host.h"
    #include "cy_sysint.h"
    
  2. Add global variables:
    static mtb_hal_sdhc_t * sdhc_obj_ptr;
    static cy_stc_sd_host_context_t sdhc_host_context;
    
  3. Add the interrupt handler for Memory Card Device HW:
    void sd_card_isr(void)
    {
        mtb_hal_sdhc_process_interrupt(sdhc_obj_ptr);
    }
    
  4. Add the Cy_SD_Host_IsCardConnected() function:
    bool Cy_SD_Host_IsCardConnected(SDHC_Type const *base)
    {
        (void) base;
    
        return true;
    }
    
  5. Add the function for Memory Card Device HW initialization:
    void FS_MMC_HW_CM_ConfigureHw(mtb_hal_sdhc_t * sdhc_obj)
    {
        cy_rslt_t hal_status;
        cy_en_sd_host_status_t pdl_sdhc_status;
        cy_en_sysint_status_t pdl_sysint_status;
    
        sdhc_obj_ptr = sdhc_obj;
    
        /* The SD Card should be enabled before calling any other SD Card APIs */
        Cy_SD_Host_Enable(SDHC_EMFILE_HW);
    
        pdl_sdhc_status = Cy_SD_Host_Init(SDHC_EMFILE_HW, &SDHC_EMFILE_config, &sdhc_host_context);
        if (CY_SD_HOST_SUCCESS != pdl_sdhc_status)
        {
            printf("Cy_SD_Host_Init returns error status\n\r");
            CY_ASSERT(0U);
        }
    
        pdl_sdhc_status = Cy_SD_Host_InitCard(SDHC_EMFILE_HW, &SDHC_EMFILE_card_cfg, &sdhc_host_context);
        if (CY_SD_HOST_SUCCESS != pdl_sdhc_status)
        {
            printf("Cy_SD_Host_InitCard returns error status\n\r");
            CY_ASSERT(0U);
        }
    
        hal_status = mtb_hal_sdhc_setup(sdhc_obj_ptr, &SDHC_EMFILE_sdhc_hal_config, NULL, &sdhc_host_context);
        if (CY_RSLT_SUCCESS != hal_status)
        {
            printf("mtb_hal_sdhc_setup returns error status\n\r");
            CY_ASSERT(0U);
        }
    
        cy_stc_sysint_t sdhc_isr_config =
        {
            .intrSrc = SDHC_EMFILE_IRQ,
            .intrPriority = 3U
        };
    
        pdl_sysint_status = Cy_SysInt_Init(&sdhc_isr_config, sd_card_isr);
        if (CY_SYSINT_SUCCESS != pdl_sysint_status)
        {
            printf("Cy_SysInt_Init returns error status\n\r");
            CY_ASSERT(0U);
        }
    
        NVIC_EnableIRQ((IRQn_Type) sdhc_isr_config.intrSrc);
    }
    
  6. Add EMFILE_SD_CARD to the COMPONENTS variable in the Makefile:
    COMPONENTS += EMFILE_SD_CARD
    

Common code

  1. Include the required headers:
    #include "cybsp.h"
    #include "cy_retarget_io.h"
    #include "mtb_hal_gpio.h"
    #include "mtb_hal_system.h"
    #include "FS.h"
    #include <string.h>
    #include <inttypes.h>
    
    #if defined(COMPONENT_RTOS_AWARE)
    #include "FreeRTOS.h"
    #include "task.h"
    #endif /* #if defined(COMPONENT_RTOS_AWARE) */
    
  2. Add the common defines to the project:
    #define NUM_BYTES_TO_READ_FROM_FILE         (256U)
    #define STRING_TO_WRITE                     "This is an emFile filesystem example for ModusToolbox."
    #define FILE_NAME                           "File.txt"
    
    #if defined(COMPONENT_RTOS_AWARE)
    #define EMFILE_TASK_STACK_SIZE              (1000U)
    #endif /* #if defined(COMPONENT_RTOS_AWARE) */
    
    #define DEBOUNCE_DELAY_MS                   (50U)
    
  3. Add common global variables:
    static char fileData[NUM_BYTES_TO_READ_FROM_FILE];
    static mtb_hal_gpio_t button_obj;
    
    #if defined(COMPONENT_RTOS_AWARE)
    static TaskHandle_t emfile_task_handle;
    #else
    static bool button_press = false;
    #endif /* #if defined(COMPONENT_RTOS_AWARE) */
    
  4. Add the function prototypes:
    static void user_button_callback(void *handler_arg, mtb_hal_gpio_event_t event);
    static void check_error(char *message, int error);
    static void btn_init(void);
    void retarget_io_init(void);  /* Implemented in separate file */
    
  5. Add the emFile task function:
    void emfile_task(void* arg)
    {
        U32         varU32;
        U32         numBytesToRead;
        int         error;
        FS_FILE    *filePtr;
        const char *volumeName = "";
    
        (void) arg;
    
        btn_init();
    
    #if defined (COMPONENT_EMFILE_NOR_FLASH)
        printf("Using NOR flash as storage device\n");
    #else
        printf("Using SD card as storage device\n");
    #endif
    
        FS_Init();
    
    #if defined (COMPONENT_EMFILE_NOR_FLASH)
        error = FS_FormatLLIfRequired(volumeName);
        check_error("Error in low-level formatting", error);
    #endif
    
        error = FS_IsHLFormatted(volumeName);
        check_error("Error in checking if volume is high-level formatted", error);
    
        if (error == 0)
        {
            printf("Perform high-level format\n");
            error = FS_Format(volumeName, NULL);
            check_error("Error in high-level formatting", error);
        }
    
        varU32 = FS_GetVolumeSizeKB(volumeName);
        printf("Volume size: %"PRIu32" KB\n\n", varU32);
    
        if (0U == varU32)
        {
            printf("Error in checking the volume size\n");
            CY_ASSERT(0U);
        }
    
        printf("Opening the file for reading...\n");
    
        filePtr = FS_FOpen(FILE_NAME, "r");
    
        if (filePtr != NULL)
        {
            numBytesToRead = sizeof(fileData) - 1U;
            varU32 = FS_GetFileSize(filePtr);
    
            if (varU32 < numBytesToRead)
            {
                numBytesToRead = varU32;
            }
    
            printf("Reading %"PRIu32" bytes from the file. ", numBytesToRead);
            varU32 = FS_Read(filePtr, fileData, numBytesToRead);
    
            if (varU32 != numBytesToRead)
            {
                error = FS_FError(filePtr);
                check_error("Error in reading from the file", error);
            }
    
            fileData[numBytesToRead] = '\0';
            printf("File Content:\n\"%s\"\n", fileData);
    
            error = FS_FClose(filePtr);
            check_error("Error in closing the file", error);
    
            printf("\nOpening the file for overwriting...\n");
        }
        else
        {
            printf("Unable to read. File not found.\n");
            printf("\nOpening the file for writing...\n");
        }
    
        filePtr = FS_FOpen(FILE_NAME, "w");
    
        if (filePtr != NULL)
        {
            varU32 = FS_Write(filePtr, STRING_TO_WRITE, strlen(STRING_TO_WRITE));
    
            if (varU32 != strlen(STRING_TO_WRITE))
            {
                error = FS_FError(filePtr);
                check_error("Error in writing to the file", error);
            }
    
            printf("File is written with the following message:\n");
            printf("\"%s\"\n\n", STRING_TO_WRITE);
    
            error = FS_FClose(filePtr);
            check_error("Error in closing the file", error);
    
            mtb_hal_gpio_enable_event(&button_obj, MTB_HAL_GPIO_IRQ_FALL, true);
            printf("\nPress the user button to delete the file or press reset to run the example again.\n\n");
    
            while (true)
            {
    #if defined (COMPONENT_RTOS_AWARE)
                if (1UL == ulTaskNotifyTake(pdTRUE, portMAX_DELAY))
                {
    #else
                if (button_press)
                {
                    button_press = false;
    #endif
                    cy_rslt_t result;
                    result = mtb_hal_system_delay_ms(DEBOUNCE_DELAY_MS);
                    CY_ASSERT(CY_RSLT_SUCCESS == result);
                    (void) result;
    
                    if (!mtb_hal_gpio_read(&button_obj)) { break; }
                }
            }
    
            printf("Deleting the file... \n");
    
            error = FS_Remove(FILE_NAME);
            check_error("Error in deleting the file", error);
    
            FS_Unmount(volumeName);
    
            printf("Filesystem operations completed successfully!\n");
            printf("Press reset to run the example again.\n");
        }
        else
        {
            printf("Unable to open the file for writing! Exiting...\n");
        }
    
        for (;;) {}
    }
    
  6. Add the check error function:
    static void check_error(char *message, int error)
    {
        if (error < 0)
        {
            printf("\n================================================================================\n");
            printf("\nFAIL: %s\n", message);
            printf("Error Value: %d\n", error);
            printf("emFile-defined Error Message: %s", FS_ErrorNo2Text(error));
            printf("\n================================================================================\n");
    
            while (true);
        }
    }
    
  7. Add the callback function for the user button:
    static void user_button_callback(void *handler_arg, mtb_hal_gpio_event_t event)
    {
        (void) handler_arg;
        (void) event;
    
    #if defined(COMPONENT_RTOS_AWARE)
        BaseType_t higher_priority_task_woken = pdFALSE;
        vTaskNotifyGiveFromISR(emfile_task_handle, &higher_priority_task_woken);
        portYIELD_FROM_ISR(higher_priority_task_woken);
    #else
        button_press = true;
    #endif
    }
    
  8. Add the interrupt handler for the user button:
    void btn_isr(void)
    {
        mtb_hal_gpio_process_interrupt(&button_obj);
    }
    
  9. Add the function for user button initialization:
    static void btn_init(void)
    {
        cy_en_sysint_status_t pdl_sysint_status;
    
        mtb_hal_gpio_setup(&button_obj, CYBSP_USER_BTN_PORT_NUM, CYBSP_USER_BTN_PIN);
        mtb_hal_gpio_configure(&button_obj, MTB_HAL_GPIO_DIR_INPUT, MTB_HAL_GPIO_DRIVE_PULLUP);
        mtb_hal_gpio_register_callback(&button_obj, user_button_callback, NULL);
    
        cy_stc_sysint_t btn_isr_config =
        {
            .intrSrc = CYBSP_USER_BTN_IRQ,
            .intrPriority = 3U
        };
    
        pdl_sysint_status = Cy_SysInt_Init(&btn_isr_config, btn_isr);
        if (CY_SYSINT_SUCCESS != pdl_sysint_status)
        {
            printf("Cy_SysInt_Init returns error status\n\r");
        }
    
        NVIC_EnableIRQ((IRQn_Type) btn_isr_config.intrSrc);
    }
    
  10. Update main():
    retarget_io_init();
    
    printf("************* emFile FAT Filesystem ************* \n\n");
    
    #if defined (COMPONENT_RTOS_AWARE)
    xTaskCreate(emfile_task, "emFile Task", EMFILE_TASK_STACK_SIZE,
                NULL, (configMAX_PRIORITIES - 1), &emfile_task_handle);
    vTaskStartScheduler();
    #else
    emfile_task(NULL);
    #endif
    

retarget-io configuration

  1. Add the retarget-io configuration function:
    void retarget_io_init(void)
    {
        cy_rslt_t result;
    
        static cy_stc_scb_uart_context_t DEBUG_UART_context;
        static mtb_hal_uart_t            DEBUG_UART_hal_obj;
    
        result = (cy_rslt_t)Cy_SCB_UART_Init(DEBUG_UART_HW, &DEBUG_UART_config, &DEBUG_UART_context);
        if (result != CY_RSLT_SUCCESS) { CY_ASSERT(0); }
    
        Cy_SCB_UART_Enable(DEBUG_UART_HW);
    
        result = mtb_hal_uart_setup(&DEBUG_UART_hal_obj, &DEBUG_UART_hal_config, &DEBUG_UART_context, NULL);
        if (result != CY_RSLT_SUCCESS) { CY_ASSERT(0); }
    
        result = cy_retarget_io_init(&DEBUG_UART_hal_obj);
        if (result != CY_RSLT_SUCCESS) { CY_ASSERT(0); }
    
        /* \x1b[2J\x1b[;H - ANSI ESC sequence for clear screen */
        printf("\x1b[2J\x1b[;H");
        printf("Retarget-io is configured\n\r");
    }
    

Project Execution

  1. Open a serial terminal. Set the serial port parameters to 8N1 and 115200 baud.
  2. Build and program the project.
  3. If the previous steps were correct, logs will appear in the serial terminal.
  4. The example initializes the emFile file system on the target memory device, creates a file, and writes data to it. Click the user button to delete the file.
Expected Serial Output

First run (no file present on the storage device):

Retarget-io is configured
************* emFile FAT Filesystem *************

Using SD card as storage device
Volume size: XXXX KB

Opening the file for reading...
Unable to read. File not found.

Opening the file for writing...
File is written with the following message:
"This is an emFile filesystem example for ModusToolbox."

Press the user button to delete the file or press reset to run the example again.

After pressing the user button:

Deleting the file...
Filesystem operations completed successfully!
Press reset to run the example again.

Subsequent runs (file present from previous run):

Reading XX bytes from the file. File Content:
"This is an emFile filesystem example for ModusToolbox."

Opening the file for overwriting...
File is written with the following message:
"This is an emFile filesystem example for ModusToolbox."

Select the FAT Library Variant

Add one of the following values to the COMPONENTS variable in the Makefile based on your FAT requirements:

COMPONENTFAT support
EMFILE_FAT16FAT 12 and FAT 16
EMFILE_FAT32FAT 12, FAT 16, and FAT 32

The correct pre-built library is selected automatically based on the CORE, VFP_SELECT, and TOOLCHAIN Makefile variables.

Configuring the HW Layer for the NOR Flash Block Map Driver (NOR_BM)

Configure the HW layer for the Block Map NOR driver in FS_X_AddDevices() before adding the driver using FS_AddDevice(). Use the configuration template from export/config/COMPONENT_EMFILE_NOR_FLASH/FS_ConfigNOR_BM_SPIFI.c as a starting point. Add EMFILE_NOR_FLASH to the COMPONENTS variable to include the template file in the build.

The template provides a weak FS_NOR_HW_SPIFI_ConfigureHw() function that must be implemented in the user application with the actual SMIF peripheral initialization.

Note: The NOR HW layer supports up to four memories using four slave select pins, but all memories must be connected to the same data lines.

Configuring the HW Layer for the SD/MMC Driver

Configure the HW layer for the SD/MMC driver in FS_X_AddDevices() before adding the driver using FS_AddDevice(). Use the configuration template from export/config/COMPONENT_EMFILE_SD_CARD/FS_ConfigMMC_CM_HS.c as a starting point. Add EMFILE_SD_CARD to the COMPONENTS variable to include the template file in the build.

The template provides a weak FS_MMC_HW_CM_ConfigureHw() function that must be implemented in the user application with the actual SDHC peripheral initialization.

XIP Support – Code and emFile on the Same NOR Flash (optional)

To share the NOR flash between code execution (XIP) and emFile storage:

  1. Add ENABLE_XIP_EMFILE_ON_SAME_NOR_FLASH to the DEFINES variable in the Makefile.
  2. Update the linker script to place FS_NOR_HW_SPIFI.o and FS_ConfigNOR_BM_SPIFI.o in a memory region not used by emFile (for example, SRAM). Ensure that SysLib, SMIF, and Memory SPI driver source files are in the same region.
  3. Implement the blocking read/write/erase completion functions as shown in FS_ConfigNOR_BM_SPIFI.c.
  4. Provide SRAM buffers for logic sector data and parameters.

Note: When XIP support is enabled, asynchronous read/write in RTOS environments is not supported. On multi-core systems, other cores that share the same NOR flash for code execution may lose access to the memory during write or erase operations.

Known Issues and Limitations

  • Supported SD bus speed modes are Default speed and High speed. Ultra High Speed (UHS) modes such as SDR 12, SDR25, and SDR50 requiring 1.8-V signaling are not supported. These modes will be supported in the future.

  • emFile always selects the 256 kB erase sector size for S25FS128S. If S25FS128S is configured to use another erase sector size, this parameter can be set by the FS_NOR_SPIFI_SetSectorSize() function inside FS_X_AddDevices(). By default, for S25FS128S, the erase sector size is 64 kB.

  • Octal SPI is not supported for NOR flash storage.

  • emFile does not support working with memories that need configuration in the secure core from the non-secure core for Edge devices.

Troubleshooting

SymptomLikely causeFix
Build error: emFile library not foundCOMPONENTS not setAdd EMFILE_FAT16 or EMFILE_FAT32 and the storage driver (EMFILE_SD_CARD or EMFILE_NOR_FLASH) to COMPONENTS in the Makefile
FS_Init() hangs or assertsHW peripheral not initializedEnsure FS_MMC_HW_CM_ConfigureHw() or FS_NOR_HW_SPIFI_ConfigureHw() completes successfully before calling FS_Init()
SD card not detectedCard missing or SDHC misconfiguredVerify SD card is inserted; confirm SDHC pins are assigned in Device Configurator using the SDHC_EMFILE alias
"Error in low-level formatting"NOR flash device not respondingCheck SMIF pin assignments and clock frequency in Device Configurator; verify EMFILE_NOR_FLASH is in COMPONENTS
No output on serial terminalWrong port or baud rateSet terminal to 115200 baud, 8N1; confirm DEBUG_UART alias and UART pins in Device Configurator
RTOS build failsMissing FreeRTOS or RTOS_AWAREAdd RTOS_AWARE FREERTOS to COMPONENTS and add the FreeRTOS library via Library Manager

Supported Devices

  • PSoC(TM) Edge E84 MCUs

Release Notes

  • RELEASE.md – Detailed release notes for all versions.

More Information

License

This software is provided under the Infineon End User License Agreement.

  • LICENSE – Infineon End User License Agreement

© 2021-2026 Infineon Technologies AG, or an affiliate of Infineon Technologies AG. All rights reserved.