eclipse-threadx/filex

fx_fault_tolerant for user data consistency

Closed this issue · 4 comments

Hi. I'm trying to use FileX + LevelX on the AT45DB641E dataflash. I connected AT45 as NAND flash page size 256 + 8 bytes. I want to use the fx_fault_tolerant module to provide the integrity of the file system and to ensure consistency data in the user files.
example:

image

I'm overwriting the same file.
fx_file_current_file_size is always 600 bytes.
The value returned by the functions is always 0.
I want the data in the file to remain consistent if there is an unexpected loss of power.
My problem is that the free disk space is leaking.

iteration - free space
0 - 6979584
1 - 6975488
2 - 6971392
3 - 6967296
4 - 6963200
5 - 6959104
6 - 6955008
7 - 6950912
8 - 6946816
9 - 6942720
.... //free space leak
N - 6868992
....

My assumption is that there are lost clusters remaining in the FAT.
lx_nand_flash_free_pages decreases.
fx_media_available_clusters decreases.

question 1)
Can I use the fx_fault_tolerant module to ensure the integrity of user data?
question 2)
Can you tell me what I'm doing wrong?
question 3)
Can I increase the value of the internal definition
#define FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE 3072
to increase the maximum size of a user transaction?

test function code:

void TransactionTest()
{
    DFNANDInstance_t df;
    
    DfNANDGetInstance(0, &df);
    df.chipErase();

    FSFXLXNANDFlashInit();

    uint32_t status;
    LX_NAND_FLASH* nand = LXNandGet();

    static UCHAR   faultTolerantMemory[FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE];
    static uint8_t fxMemBuf[8 * 1024];
    static FX_MEDIA fxDisk;

    memset(&fxDisk, 0, sizeof(fxDisk));
    memset(fxMemBuf, 0, sizeof(fxMemBuf));

    _fx_system_initialize();

    uint32_t sectorToFat =
            nand->lx_nand_flash_total_pages -
            nand->lx_nand_flash_total_blocks - 1 -
            nand->lx_nand_flash_pages_per_block * 15; //15 blocks reserved

    status = _fx_media_format(&fxDisk,
                              FSFXNandFlashDriver,          // Driver entry
                              0,                 // RAM disk memory pointer
                              fxMemBuf,                     // Media buffer pointer
                              sizeof(fxMemBuf),             // Media buffer size
                              "C",               // Volume Name
                              1,                // Number of FATs
                              32,              // Directory Entries
                              8,                // Hidden sectors
                              sectorToFat,                  // Total sectors
                              256,             // Sector size
                              16,             // Sectors per cluster
                              1,                      // Heads
                              1);              // Sectors per track

    if (status) flt();

    memset(&fxDisk, 0, sizeof(fxDisk));
    memset(fxMemBuf, 0, sizeof(fxMemBuf));
    memset(faultTolerantMemory, 0, sizeof(faultTolerantMemory));

    status =  _fx_media_open(&fxDisk, "C", FSFXNandFlashDriver, 0, fxMemBuf, sizeof(fxMemBuf));
    if (status) flt();

    status = _fx_fault_tolerant_enable(&fxDisk, faultTolerantMemory, sizeof(faultTolerantMemory));
    if (status) flt();

    static uint8_t data1[300];
    static uint8_t data2[300];
    memset(data1, 0xAA, sizeof(data1));
    memset(data2, 0xBB, sizeof(data2));

    while (1) {
        ULONG space;
        FX_FILE file;

        status = _fx_media_space_available(&fxDisk, &space);
        if (status) flt();

        status = _fx_fault_tolerant_transaction_start(&fxDisk);
        if (status) flt();

                status =  _fx_file_create(&fxDisk, "test.txt");
                if (status != FX_ALREADY_CREATED && status != FX_SUCCESS) flt();

                status = _fx_file_open(&fxDisk, &file, "test.txt", FX_OPEN_FOR_WRITE);
                if (status) flt();

                status = _fx_file_seek(&file, 0);
                if (status) flt();

                status = _fx_file_write(&file, data1, 300);
                if (status) flt();
                status = _fx_file_write(&file, data2, 300);
                if (status) flt();

                status = _fx_file_close(&file);
                if (status) flt();

        status = _fx_fault_tolerant_transaction_end(&fxDisk);
        if (status) flt();

        status = _lx_nand_flash_defragment(nand);
        if (status) flt();
    }
}

Hi, all the AzureRTOS APIs starts with tx_/nx_/fx_/... In user application, don't call to tx/nx/fx/... directly. Those could be internal functions. In your example, _fx_fault_tolerant_transaction_start/end are internal functions. The only API needed to enable fault tolerant is fx_fault_tolerant_enable.

See my answers below.
question 1)
Can I use the fx_fault_tolerant module to ensure the integrity of user data?
[MSFT]: Yes.
question 2)
Can you tell me what I'm doing wrong?
[MSFT]: Internal functions must not be called.
question 3)
Can I increase the value of the internal definition
#define FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE 3072
to increase the maximum size of a user transaction?
[MSFT]: No. This size is defined for the maximum log file size. No transaction would create a larger log file than this value.

OK, thanks.
Another question:
Is there an interface in FileX, to provide write transactions that consist of multiple write(...)?

example:
image

I would like, after restarting, to have either three successful writes or none in the file.
Depending on when the failure occurred.
Of course, this can be implemented through a temporary file and the subsequent renaming of the file.
I just wanted to understand - maybe FileX has a ready-made mechanism?
Thanks.

No, there is no FileX service to protect multiple transactions. Besides a temporary file, another solution is to write all data into a buffer and then write buffer to file system in one fx_file_write call.

I got it, thanks.