This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

zb_nvram_write_dataset writing application data zigbee

Is there any code example for storing application data using the zboss stack? I have only found this:

There are two predefined dataset IDs for a user application: ZB_NVRAM_APP_DATA1 and ZB_NVRAM_APP_DATA2. It's up to the application to decide what data to store in NVRAM. However, the total data size (all datasets) stored in the NVRAM storage should be less than one virtual page size. To start using NVRAM in the application, the following steps should be done in the application:

@li Define an application specific data structure to be stored in the NVRAM.
@li Register callbacks to write, read data and get size of data to store.
@li Once write application data callback is called, it gets a flash page number and a page offset value to store data. The callback must write data using an API zb_osif_nvram_write(). The data size must be the same as returned by a get data size callback.
@li Once get data size callback is called, it must return the size of the data being stored.
@li Once the read application data callback is called, it gets a flash page number, a page offset value, and a payload size of data to read. The callback reads the data using an API zb_osif_nvram_read() with the provided addressing information as input parameters.
@li At runtime trigger storing data to NVRAM with a call to zb_nvram_write_dataset().

I have not been able to successfully store data. Any code snippet? Could you help me with this?

thx

Parents
  • Hi Armand.

    Could you take a look here, at the bottom of this page is some examples.

    Best regards,

    Andreas

  • Hi Andreas,

    Thanks for pointing to the example. Somehow there is some doubts casting on my head:

    1. I am supposing that when the application code calls zb_nvram_write_dataset(ZB_NVRAM_APP_DATA1) the 

    write cb read_thc_app_data_cb is called back and the data is stored through zb_osif_nvram_write(page, pos, (zb_uint8_t*)&dssizeof(ds)). Is that correct?

    2. Now it is required to read the data back. I have defined the read_thc_app_data_cb. How is that function triggered? I cannot see any zb_nvram_read_dataset function declared.

    3. Finally. Let suppose I would like to read the data after a power cycle. Relevant info required to read the data from nvram will not be available on ram variables(page, pos) as they have been reset. Are we missing a zb_nvram_read_dataset that will will trigger the read_thc_app_data_cb and pass the correct (page, pos) data?

    Thanks

  • Hi.

    Do you really need to use the ZBOSS stack? If yes I will give you more details.

    But if you don't really need to use the ZBOSS stack to write to flash, I will recommend that you use the FDS module.

    It is an working example found in the multiprotocol example for the door lock (examples\multiprotocol\ble_zigbee\ble_zigbee_dynamic_door_lock_nus\) you can take a look at.

    And it is more documented than ZB_NVRAM:

    FDS moduleAPI reference, Usage.

    Best regards,

    Andreas

  • Thanks Andreas. Yes I would like to be able to use the ZBOSS stack as I am planning to use the nRF52811 device. I presume that future SDK releases will not bring the option of multiprotocol application to this device due to memory restrictions.

    Is is possible to use FDS module while running ZBOSS stack? Is there any risk of collision or data storage misshandling?

    Anyway I would also like to know how to read the nvram data using zb library. Is the current SDK version missing a  zb_nvram_read_dataset function?

  • Hi again.

    Ignacio said:
    I presume that future SDK releases will not bring the option of multiprotocol application to this device due to memory restrictions.

    I think it wouldn't be feasible to use multiprotocol in nRF52811 due to the FLASH and RAM size yes, but you can use FDS without using the SoftDevice.

    An example of FDS is found in <InstallFolder>\examples\peripheral\flash_fds

    FDS uses fstorage at the base, and neither require much code. The part that takes most space would be that you have to reserve two flash pages in order to use it.

    Ignacio said:
    Anyway I would also like to know how to read the nvram data using zb library. Is the current SDK version missing a  zb_nvram_read_dataset function?

     There is no zb_nvram_read_dataset function, reading is done by zb_osif_nvram_read() in the read_thc_app_data_cb().

    Best regards,

    Andreas

  • Thanks Andreas. Let's see if we can clarify further how to read the data. In the example code here and as you mention reading is done by zb_osif_nvram_read() in the read_thc_app_data_cb(). To the function callback read_thc_app_data_cb() are parsed three parameters (zb_uint8_t page, zb_uint32_t pos, zb_uint16_t payload_length). From my understanding it should be an app function that will trigger the system to call and parse the info to this callback. To sum up, how is read_thc_app_data_cb()  called?

    Regards

Reply Children
  • Hi again.

    Ignacio said:
    how is read_thc_app_data_cb()  called?

     It is called when the ZBOSS stack is started.

    I do still recommend that you use FDS for your project.

    Best regards,

    Andreas

  • How do I know if the data stored is valid or if the device just boot for the first time?

  • Hi Armand,
    first of all, it is good to understand how does the ZB_NVRAM works and what are the design assumptions.

    The ZB_NVRAM works like some kind of a "log". It stores predefined datasets with a version identifier one after another inside flash pages, reserved for the Zigbee stack. If you request to store the dataset, the stack does not perform erase cycle, but tries to append the never version of your dataset inside the free space of flash memory, with never version ID. The version ID, as well as page migration is fully managed by the stack and you do not have to care about them. This version-ID-enabled method of writing is used in order to prevent you from loosing a valid dataset value, once the device got reset while performing flash operation. In such case, your dataset will be restored from the last, correctly written state.

    The NVRAM logic is pretty straightforward. After the "zboss_start*" call, the stack reads the whole flash page and looks for the newest, valid version of each dataset. At this point, the read/load callback is called. The callback should store the read value inside the RAM using its own static/global variable.

    Afterwards, it is assumed that the application uses the static/global variable to perform changes or read dataset field values.

    Whenever needed, the application should call the "zb_nvram_write_dataset(ZB_NVRAM_APP_DATA*)" in order to store the newer version of dataset inside the flash. Keep in mind that every flash operation halts the CPU and consumes flash write cycles, so flushing every change may not be a good idea in all cases. Every call to the "zb_nvram_write_dataset" triggers the write/store callback. The callback should get the static/global variable and use the OSIF NVRAM API to store its current value.

    If there is no user dataset stored inside the flash, the callback will not be called, so please remember to initialize the static/global variable with valid default values before calling "zboss_start*".

    Getting back to your questions:

    1. It is assumed that the data stored via write/store callback is always valid. The stack returns only a single dataset version and its integrity is verified by the stack (if a call to the flash after the user write/store callback succeed - the dataset version is marked as valid).
    2. I would suggest to check if the read/load callback was called before "ZB_BDB_SIGNAL_DEVICE_FIRST_START" or "ZB_BDB_SIGNAL_DEVICE_REBOOT" signals. That way you will be 100% sure that no valid dataset was present inside NVRAM during boot-up.

    Code snippets to get started:

    static my_dataset_t m_my_dataset;
    
    ...
    
    zb_uint16_t my_dataset_get_size(void)
    {
        return sizeof(my_dataset_t);
    }
    
    zb_void_t my_dataset_load(zb_uint8_t page, zb_uint32_t pos, zb_uint16_t payload_length)
    {
        zb_ret_t ret = RET_ERROR;
    
        if (payload_length == sizeof(my_dataset_t))
        {
            ret = zb_osif_nvram_read(page, pos, (zb_uint8_t*)&m_my_dataset, sizeof(my_dataset_t));
        }
    
        UNUSED_VARIABLE(ret);
        NRF_LOG_INFO("Loading my dataset. Status: %d", ret);
    }
    
    zb_ret_t my_dataset_store(zb_uint8_t page, zb_uint32_t pos)
    {
        zb_ret_t ret;
    
        ret = zb_osif_nvram_write(page, pos, (zb_uint8_t*)&m_my_dataset, sizeof(my_dataset_t));
    
        NRF_LOG_INFO("Storing my dataset. Status: %d", ret);
        return ret;
    }
    
    ...
    
    zb_nvram_register_app1_read_cb(my_dataset_load);
    zb_nvram_register_app1_write_cb(my_dataset_store, my_dataset_get_size);
    
    ...
    
    zboss_start();

    And a small note, why the ZB_NVRAM is not the advised option:

    First of all, there are several modules inside the SDK that already implements this kind of functionality, so introducing a new one may lead to further confusion (one may think that if they use Zigbee, they have to use ZB_NVRAM, which is not true. The FDS module has been adopted to avoid address conflicts with ZB_NVRAM pages - look at the "FDS_VIRTUAL_PAGES_RESERVED" definition inside sdk_config.h file).

    The second thing is that if the user application will heavily use the ZB_NVRAM, the Zigbee flash pages migration will occur much more frequently, which may result in a shorter device lifetime. If the Zigbee network datasets cannot be updated, your device will loose its ability to communicate with the rest of the network due to incorrect values inside security header (your device will start to behave like a rogue node performing replay attack).

    The third argument is the fact, that you can specify only two types of datasets that the application may store. The size of the dataset cannot be changed over time. It is sufficient for simple cases, but a complex application will easily reach this limit.

    On the other hand, using ZB_NVRAM reduces the code size footprint, as this functionality is included, regardless the application code. Just please remember to reserve as many as possible flash pages if you are about to use it, so the migration process will not brick your device too fast (all parameters can be adjusted inside external/zboss/osif/zb_nrf52840_nvram.c file).

    I hope that my explanation has all information that you need or just want to ask for Slight smile.

    Best Regards,

    Tomchy

Related