|
| 1 | +.. _settings: |
| 2 | + |
| 3 | +Settings subsystem with non-volatile storage |
| 4 | +############################################ |
| 5 | + |
| 6 | +The settings subsystem gives modules a way to store persistent |
| 7 | +per-device configuration and runtime state. |
| 8 | + |
| 9 | +Settings items are stored as key-value pair strings. By convention, |
| 10 | +the keys can be organized by the package and subtree defining the key, |
| 11 | +for example the key ``id/serial`` would define the ``serial`` configuration |
| 12 | +element for the package ``id``. |
| 13 | + |
| 14 | +Convenience routines are provided for converting a key value to |
| 15 | +and from a string type. |
| 16 | + |
| 17 | +Handlers |
| 18 | +******** |
| 19 | + |
| 20 | +Settings handlers for subtree implement a set of handler functions. |
| 21 | +These are registered using a call to ``settings_register()``. |
| 22 | + |
| 23 | +**h_get** |
| 24 | + This gets called when asking for a settings element value |
| 25 | + by its name using ``settings_get_value()``. |
| 26 | + |
| 27 | +**h_set** |
| 28 | + This gets called when the value is being set using ``settings_set_value()``, |
| 29 | + and also when setting is loaded from persisted storage with |
| 30 | + ``settings_load()``. |
| 31 | + |
| 32 | +**h_commit** |
| 33 | + This gets called after the settings have been loaded in full. |
| 34 | + Sometimes you don't want an individual setting value to take |
| 35 | + effect right away, for example if there are multiple settings |
| 36 | + which are interdependent. |
| 37 | + |
| 38 | +**h_export** |
| 39 | + This gets called to write all current settings. This happens |
| 40 | + when ``settings_save()`` tries to save the settings or transfer to any |
| 41 | + user-implemented back-end. |
| 42 | + |
| 43 | +Persistence |
| 44 | +*********** |
| 45 | + |
| 46 | +Backend storage for the settings can be either FCB, a file in the filesystem, |
| 47 | +or both. |
| 48 | + |
| 49 | +You can declare multiple sources for settings; settings from |
| 50 | +all of these are restored when ``settings_load()`` is called. |
| 51 | + |
| 52 | +There can be only one target for writing settings; this is where |
| 53 | +data is stored when you call ``settings_save()``, or ``settings_save_one()``. |
| 54 | + |
| 55 | +FCB read target is registered using ``settings_fcb_src()``, and write target |
| 56 | +using ``settings_fcb_dst()``. As a side-effect, ``settings_fcb_src()`` |
| 57 | +initializes the FCB area, so it must be called before calling |
| 58 | +``settings_fcb_dst()``. File read target is registered using |
| 59 | +``settings_file_src()``, and write target by using ``settings_file_dst()``. |
| 60 | + |
| 61 | +Example: Device Configuration |
| 62 | +***************************** |
| 63 | + |
| 64 | +This is a simple example, where the settings handler only implements ``ch_set`` |
| 65 | +and ``ch_export``. ``ch_set`` is called when the value is restored from storage |
| 66 | +(or when set initially), and ``ch_export`` is used to write the value to |
| 67 | +storage thanks to ``storage_func()``. The user can also implement some other |
| 68 | +export functionality, for example, writing to the shell console). |
| 69 | + |
| 70 | +.. code-block:: c |
| 71 | +
|
| 72 | + static int8 foo_val; |
| 73 | +
|
| 74 | + struct settings_handler my_conf = { |
| 75 | + .ch_name = "foo", |
| 76 | + .ch_set = foo_settings_set, |
| 77 | + .ch_export = foo_settings_export |
| 78 | + } |
| 79 | +
|
| 80 | + static int foo_settings_set(int argc, char **argv, char *val) |
| 81 | + { |
| 82 | + if (argc == 1) { |
| 83 | + if (!strcmp(argv[0], "bar")) { |
| 84 | + return SETTINGS_VALUE_SET(val, SETTINGS_INT8, foo_val); |
| 85 | + } |
| 86 | + } |
| 87 | +
|
| 88 | + return -ENOENT; |
| 89 | + } |
| 90 | +
|
| 91 | + static int foo_settings_export(void (*storage_func)(char *name, char *val), |
| 92 | + enum settings_export_tgt tgt) |
| 93 | + { |
| 94 | + char buf[4]; |
| 95 | +
|
| 96 | + settings_str_from_value(SETTINGS_INT8, &foo_val, buf, sizeof(buf)); |
| 97 | + storage_func("foo/bar", buf) |
| 98 | +
|
| 99 | + return 0; |
| 100 | + } |
| 101 | +
|
| 102 | +Example: Persist Runtime State |
| 103 | +****************************** |
| 104 | + |
| 105 | +This is a simple example showing how to persist runtime state. In this example, |
| 106 | +only ``ch_set`` is defined, which is used when restoring value from |
| 107 | +persisted storage. |
| 108 | + |
| 109 | +In this example, the ``foo_callout`` function increments ``foo_val``, and then |
| 110 | +persists the latest number. When the system restarts, the application calls |
| 111 | +``settings_load()`` while initializing, and ``foo_val`` will continue counting |
| 112 | +up from where it was before restart. |
| 113 | + |
| 114 | +.. code-block:: c |
| 115 | +
|
| 116 | + static int8 foo_val; |
| 117 | +
|
| 118 | + struct settings_handler my_conf = { |
| 119 | + .ch_name = "foo", |
| 120 | + .ch_set = foo_settings_set |
| 121 | + } |
| 122 | +
|
| 123 | + static int foo_settings_set(int argc, char **argv, char *val) |
| 124 | + { |
| 125 | + if (argc == 1) { |
| 126 | + if (!strcmp(argv[0], "bar")) { |
| 127 | + return SETTINGS_VALUE_SET(val, SETTINGS_INT8, foo_val); |
| 128 | + } |
| 129 | + } |
| 130 | +
|
| 131 | + return -ENOENT; |
| 132 | + } |
| 133 | +
|
| 134 | + static void foo_callout(struct os_event *ev) |
| 135 | + { |
| 136 | + struct os_callout *c = (struct os_callout *)ev; |
| 137 | + char buf[4]; |
| 138 | +
|
| 139 | + foo_val++; |
| 140 | + settings_str_from_value(SETTINGS_INT8, &foo_val, buf, sizeof(buf)); |
| 141 | + settings_save_one("foo/bar", bar); |
| 142 | +
|
| 143 | + k_sleep(1000); |
| 144 | + sys_reboot(SYS_REBOOT_COLD); |
| 145 | + } |
| 146 | +
|
| 147 | +API |
| 148 | +*** |
| 149 | + |
| 150 | +The Settings subsystem APIs are provided by ``settings.h``: |
| 151 | + |
| 152 | +.. doxygengroup:: settings |
| 153 | + :project: Zephyr |
| 154 | + |
0 commit comments