1 /*
2 * Copyright (c) 2018-2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdio.h>
8 #include <zephyr/ztest.h>
9
10 #include <zephyr/kernel.h>
11 #include <zephyr/sys/reboot.h>
12 #include <string.h>
13
14 #include <zephyr/settings/settings.h>
15 #include <zephyr/storage/flash_map.h>
16 #include <zephyr/drivers/flash.h>
17
18 #define TEST_PARTITION storage_partition
19 #define CODE_PARTITION slot0_partition
20
21 #define TEST_PARTITION_ID FIXED_PARTITION_ID(TEST_PARTITION)
22
23 #define CODE_PARTITION_NODE DT_NODELABEL(CODE_PARTITION)
24 #define CODE_PARTITION_ID FIXED_PARTITION_ID(CODE_PARTITION)
25 #define CODE_PARTITION_EXISTS FIXED_PARTITION_EXISTS(CODE_PARTITION)
26
27 static uint32_t val32;
28
29 #if defined(CONFIG_SOC_SERIES_STM32L0X) || defined(CONFIG_SOC_SERIES_STM32L0X)
30 #define ERASED_VAL 0x00
31 #else
32 #define ERASED_VAL 0xFF
33 #endif
34
35 /* leverage that this area has to be embedded flash part */
36 #if CODE_PARTITION_EXISTS
37 #if DT_NODE_HAS_PROP(DT_GPARENT(CODE_PARTITION_NODE), write_block_size)
38 #define FLASH_WRITE_BLOCK_SIZE \
39 DT_PROP(DT_GPARENT(CODE_PARTITION_NODE), write_block_size)
40 static const volatile __attribute__((section(".rodata")))
41 __aligned(FLASH_WRITE_BLOCK_SIZE)
42 uint8_t prepared_mark[FLASH_WRITE_BLOCK_SIZE] = {ERASED_VAL};
43 #else
44 #error "Test not prepared to run from flash with no write-block-size property in DTS"
45 #endif
46 #endif
47
c1_set(const char * name,size_t len,settings_read_cb read_cb,void * cb_arg)48 static int c1_set(const char *name, size_t len, settings_read_cb read_cb,
49 void *cb_arg)
50 {
51 int rc;
52 const char *next;
53
54 if (settings_name_steq(name, "val32", &next) && !next) {
55 rc = read_cb(cb_arg, &val32, sizeof(val32));
56 zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
57 return 0;
58 }
59
60 return -ENOENT;
61 }
62
c1_export(int (* export_func)(const char * name,const void * value,size_t val_len))63 static int c1_export(int (*export_func)(const char *name,
64 const void *value, size_t val_len))
65 {
66 (void)export_func("hello/val32", &val32, sizeof(val32));
67
68 return 0;
69 }
70
71 static struct settings_handler c1_settings = {
72 .name = "hello",
73 .h_set = c1_set,
74 .h_export = c1_export,
75 };
76
ZTEST(fcb_initialization,test_init)77 ZTEST(fcb_initialization, test_init)
78 {
79 int err;
80 uint32_t prev_int;
81
82 val32++;
83
84 err = settings_save();
85 zassert_true(err == 0, "can't save settings");
86
87 prev_int = val32;
88 val32 = 0U;
89 err = settings_load();
90 zassert_true(err == 0, "can't load settings");
91 zassert_equal(prev_int, val32,
92 "load value doesn't match to what was saved");
93 }
94
95
test_prepare_storage(void)96 void test_prepare_storage(void)
97 {
98 #if CODE_PARTITION_EXISTS
99 /* This procedure uses mark which is stored inside SoC embedded program
100 * flash. It will not work on devices on which read/write to them is not
101 * possible.
102 */
103 int err;
104 const struct flash_area *fa;
105 const struct device *dev;
106 uint8_t new_val[FLASH_WRITE_BLOCK_SIZE];
107
108 if (prepared_mark[0] == ERASED_VAL) {
109 TC_PRINT("First run: erasing the storage\r\n");
110 err = flash_area_open(TEST_PARTITION_ID, &fa);
111 zassert_true(err == 0, "Can't open storage flash area");
112
113 err = flash_area_flatten(fa, 0, fa->fa_size);
114 zassert_true(err == 0, "Can't erase storage flash area");
115
116 err = flash_area_open(CODE_PARTITION_ID, &fa);
117 zassert_true(err == 0, "Can't open storage flash area");
118
119 dev = flash_area_get_device(fa);
120
121 (void)memset(new_val, (~ERASED_VAL) & 0xFF,
122 FLASH_WRITE_BLOCK_SIZE);
123 err = flash_write(dev, (off_t)&prepared_mark, &new_val,
124 sizeof(new_val));
125 zassert_true(err == 0, "can't write prepared_mark");
126 }
127 #else
128 TC_PRINT("Storage preparation can't be performed\r\n");
129 TC_PRINT("Erase storage manually before test flashing\r\n");
130 #endif
131 }
132
test_init_setup(void)133 void *test_init_setup(void)
134 {
135 int err;
136
137 test_prepare_storage();
138
139 err = settings_subsys_init();
140 zassert_true(err == 0, "subsys init failed");
141
142 err = settings_register(&c1_settings);
143 zassert_true(err == 0, "can't register the settings handler");
144
145 err = settings_load();
146 zassert_true(err == 0, "can't load settings");
147
148 if (val32 < 1) {
149 val32 = 1U;
150 err = settings_save();
151 zassert_true(err == 0, "can't save settings");
152 k_sleep(K_MSEC(250));
153 sys_reboot(SYS_REBOOT_COLD);
154 }
155 return NULL;
156 }
157
158 ZTEST_SUITE(fcb_initialization, NULL, test_init_setup, NULL, NULL, NULL);
159