ZMS on nRF54L15DK

Hi

I am working with the zephyr ZMS sample application.
I am using SDK 2.9.0, and I built the application for the nRF54L15DK (nrf54l15dk/nrf54l15/cpuapp).
The sample works.
The problem I am having is when I try and port this code to my existing nRF54L15DK project.

Apologies, this is a long read, with the issue detailed near the end.

When I build the sample application, this is the partion.yml after the build:

app:
address: 0x0
end_address: 0x15f000
region: flash_primary
size: 0x15f000
otp:
address: 0xffd500
end_address: 0xffd9fc
region: otp
size: 0x4fc
sram_primary:
address: 0x20000000
end_address: 0x2002f000
region: sram_primary
size: 0x2f000
zms_storage:
address: 0x15f000
end_address: 0x165000
placement:
after:
- app
before:
- end
region: flash_primary
size: 0x6000

And the code works – the filing system is mounted etc.

I want to bring some of this code in to my own nRF54L15DK project, and to do this, I want to specify the location of the zms_storage, so that I know it will be at a fixed location, always.

So, as an experiment, in the sample application I created a pm_static.yml file, with the addresses that the partition manager craeted before there was a pm_static.yml file:


zms_storage:
address: 0x15f000
size: 0x6000
end_address: 0x165000
placement:
before:
- end
region: flash_primary

The only update to the partition.yml file, is that for the zms_storage, the placement is now:


placement:
before:
- end

And not:

placement:
after:
- app
before:
- end

And it no surprise that the code still works, because no addresses have been changed etc.

So now I go to my project. Before I try and add ZMS, this is my partition.yml:


app:
address: 0x0
end_address: 0x163000
region: flash_primary
size: 0x163000
otp:
address: 0xffd500
end_address: 0xffd9fc
region: otp
size: 0x4fc
settings_storage:
address: 0x163000
end_address: 0x165000
placement:
after:
- app
before:
- end
region: flash_primary
size: 0x2000
sram_primary:
address: 0x20000000
end_address: 0x2002f000
region: sram_primary
size: 0x2f000

So where should I place the zms storage?

I tried to tag it on to the end of settings_storage, with this pm_static.yml:


zms_storage:
address: 0x15f000
size: 0x6000
end_address: 0x165000
placement:
before:
- end
region: flash_primary

This results in the following partition.yml:


app:
address: 0x0
end_address: 0x163000
region: flash_primary
size: 0x163000
otp:
address: 0xffd500
end_address: 0xffd9fc
region: otp
size: 0x4fc
settings_storage:
address: 0x163000
end_address: 0x165000
placement:
after:
- app
before:
- end
region: flash_primary
size: 0x2000
sram_primary:
address: 0x20000000
end_address: 0x2002f000
region: sram_primary
size: 0x2f000
zms_storage:
address: 0x165000
end_address: 0x16b000
placement:
before:
- end
region: flash_primary
size: 0x6000

I also made the following modification to the zms code, to use the defined zms_storage:

// #define ZMS_PARTITION storage_partition
// #define ZMS_PARTITION_DEVICE FIXED_PARTITION_DEVICE(ZMS_PARTITION)
// #define ZMS_PARTITION_OFFSET FIXED_PARTITION_OFFSET(ZMS_PARTITION)
#define ZMS_PARTITION zms_storage
#define ZMS_PARTITION_DEVICE FIXED_PARTITION_DEVICE(ZMS_PARTITION)
#define ZMS_PARTITION_OFFSET FIXED_PARTITION_OFFSET(ZMS_PARTITION)


However, when I run my code, the following line fails:

rc = flash_get_page_info_by_offs(fs.flash_device, fs.offset, &info);

(fs.offset is 0x165000)

I get error -22.

Here’s the complete function:

int zms_try(void)
{
    int rc = 0;
    char buf[16];
    //uint8_t key[8] = {0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF}, longarray[128];
    uint8_t key[8] = {0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF}, longarray[32];
    uint32_t i_cnt = 0U;
    uint32_t i;
    uint32_t id = 0;
    ssize_t free_space = 0;
    struct flash_pages_info info;

    for (int n = 0; n < sizeof(longarray); n++) {
        longarray[n] = n;
    }

    /* define the zms file system by settings with:
     *  sector_size equal to the pagesize,
     *  3 sectors
     *  starting at ZMS_PARTITION_OFFSET
     */
    fs.flash_device = ZMS_PARTITION_DEVICE;
    if (!device_is_ready(fs.flash_device)) {
        printk("Storage device %s is not ready\n", fs.flash_device->name);
        return -1;
    }
    fs.offset = ZMS_PARTITION_OFFSET;
    rc = flash_get_page_info_by_offs(fs.flash_device, fs.offset, &info);
    if (rc) {
        printk("Unable to get page info, rc=%d\n", rc);
        return -2;
    }
    fs.sector_size = info.size;
    fs.sector_count = 3U;

    for (i = 0; i < MAX_ITERATIONS; i++) {
        rc = zms_mount(&fs);
        if (rc) {
            printk("Storage Init failed, rc=%d\n", rc);
            return -3;
        }

        printk("ITERATION: %u\n", i);
        /* IP_ADDRESS_ID is used to store an address, lets see if we can
         * read it from flash, since we don't know the size read the
         * maximum possible
         */
        rc = zms_read(&fs, IP_ADDRESS_ID, &buf, sizeof(buf));
        if (rc > 0) {
            /* item was found, show it */
            buf[rc] = '\0';
            printk("ID: %u, IP Address: %s\n", IP_ADDRESS_ID, buf);
        }
        /* Rewriting ADDRESS IP even if we found it */
        strncpy(buf, "172.16.254.1", sizeof(buf) - 1);
        printk("Adding IP_ADDRESS %s at id %u\n", buf, IP_ADDRESS_ID);
        rc = zms_write(&fs, IP_ADDRESS_ID, &buf, strlen(buf));
        if (rc < 0) {
            printk("Error while writing Entry rc=%d\n", rc);
            break;
        }

        /* KEY_VALUE_ID is used to store a key/value pair , lets see if we can read
         * it from storage.
         */
        rc = zms_read(&fs, KEY_VALUE_ID, &key, sizeof(key));
        if (rc > 0) { /* item was found, show it */
            printk("Id: %x, Key: ", KEY_VALUE_ID);
            for (uint8_t n = 0; n < 8; n++) {
                printk("%x ", key[n]);
            }
            printk("\n");
        }
        /* Rewriting KEY_VALUE even if we found it */
        printk("Adding key/value at id %x\n", KEY_VALUE_ID);
        rc = zms_write(&fs, KEY_VALUE_ID, &key, sizeof(key));
        if (rc < 0) {
            printk("Error while writing Entry rc=%d\n", rc);
            break;
        }

        /* CNT_ID is used to store the loop counter, lets see
         * if we can read it from storage
         */
        if (i == 0)
        {
            rc = zms_write(&fs, CNT_ID, &i, sizeof(i));
            if (rc < 0) {
                printk("Error while writing Entry rc=%d\n", rc);
                break;
            }
        } else {
            rc = zms_read(&fs, CNT_ID, &i_cnt, sizeof(i_cnt));
            if (rc > 0) { /* item was found, show it */
                printk("Id: %d, loop_cnt: %u\n", CNT_ID, i_cnt);
                if (i_cnt != (i - 1)) {
                    break;
                }
            }
            printk("Adding counter at id %u\n", CNT_ID);
            rc = zms_write(&fs, CNT_ID, &i, sizeof(i));
            if (rc < 0) {
                printk("Error while writing Entry rc=%d\n", rc);
                break;
            }

        }

        /* LONG_DATA_ID is used to store a larger dataset ,lets see if we can read
         * it from flash
         */
        rc = zms_read(&fs, LONG_DATA_ID, &longarray, sizeof(longarray));
        if (rc > 0) {
            /* item was found, show it */
            printk("Id: %d, Longarray: ", LONG_DATA_ID);
            for (uint16_t n = 0; n < sizeof(longarray); n++) {
                printk("%x ", longarray[n]);
            }
            printk("\n");
        }
        /* Rewrite the entry even if we found it */
        printk("Adding Longarray at id %d\n", LONG_DATA_ID);
        rc = zms_write(&fs, LONG_DATA_ID, &longarray, sizeof(longarray));
        if (rc < 0) {
            printk("Error while writing Entry rc=%d\n", rc);
            break;
        }

        /* Each DELETE_ITERATION delete all basic items */
        if (!(i % DELETE_ITERATION) && (i)) {
            rc = delete_basic_items(&fs);
            if (rc) {
                break;
            }
        }
    }

    if (i != MAX_ITERATIONS) {
        printk("Error: Something went wrong at iteration %u rc=%d\n", i, rc);
        return 0;
    }

    while (1) {
        /* fill all storage */
        rc = zms_write(&fs, id, &id, sizeof(uint32_t));
        if (rc < 0) {
            break;
        }
        id++;
    }

    if (rc == -ENOSPC) {
        /* Calculate free space and verify that it is 0 */
        free_space = zms_calc_free_space(&fs);
        if (free_space < 0) {
            printk("Error while computing free space, rc=%d\n", free_space);
            return -4;
        }
        if (free_space > 0) {
            printk("Error: free_space should be 0, computed %u\n", free_space);
            return -5;
        }
        printk("Memory is full let's delete all items\n");

        /* Now delete all previously written items */
        for (uint32_t n = 0; n < id; n++) {
            rc = delete_and_verify_items(&fs, n);
            if (rc) {
                printk("Error deleting at id %u\n", n);
                return -6;
            }
        }
        rc = delete_basic_items(&fs);
        if (rc) {
            printk("Error deleting basic items\n");
            return -7;
        }
    }

    /*
     * Let's compute free space in storage. But before doing that let's Garbage collect
     * all sectors where we deleted all entries and then compute the free space
     */
    for (i = 0; i < fs.sector_count; i++) {
        rc = zms_sector_use_next(&fs);
        if (rc) {
            printk("Error while changing sector rc=%d\n", rc);
        }
    }
    free_space = zms_calc_free_space(&fs);
    if (free_space < 0) {
        printk("Error while computing free space, rc=%d\n", free_space);
        return -8;
    }
    printk("Free space in storage is %u bytes\n", free_space);

    /* Let's clean the storage now */
    rc = zms_clear(&fs);
    if (rc < 0) {
        printk("Error while cleaning the storage, rc=%d\n", rc);
    }

    printk("Sample code finished Successfully\n");

    return 0;
}

Related