| /* |
| * Copyright (c) 2018-2022 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <stdio.h> |
| #include <zephyr/ztest.h> |
| |
| #include <zephyr/kernel.h> |
| #include <zephyr/sys/reboot.h> |
| #include <string.h> |
| |
| #include <zephyr/settings/settings.h> |
| #include <zephyr/storage/flash_map.h> |
| #include <zephyr/drivers/flash.h> |
| |
| #define TEST_PARTITION storage_partition |
| #define CODE_PARTITION slot0_partition |
| |
| #define TEST_PARTITION_ID FIXED_PARTITION_ID(TEST_PARTITION) |
| |
| #define CODE_PARTITION_NODE DT_NODELABEL(CODE_PARTITION) |
| #define CODE_PARTITION_ID FIXED_PARTITION_ID(CODE_PARTITION) |
| #define CODE_PARTITION_EXISTS FIXED_PARTITION_EXISTS(CODE_PARTITION) |
| |
| static uint32_t val32; |
| |
| #if defined(CONFIG_SOC_SERIES_STM32L0X) || defined(CONFIG_SOC_SERIES_STM32L0X) |
| #define ERASED_VAL 0x00 |
| #else |
| #define ERASED_VAL 0xFF |
| #endif |
| |
| /* leverage that this area has to be embedded flash part */ |
| #if CODE_PARTITION_EXISTS |
| #if DT_NODE_HAS_PROP(DT_GPARENT(CODE_PARTITION_NODE), write_block_size) |
| #define FLASH_WRITE_BLOCK_SIZE \ |
| DT_PROP(DT_GPARENT(CODE_PARTITION_NODE), write_block_size) |
| static const volatile __attribute__((section(".rodata"))) |
| __aligned(FLASH_WRITE_BLOCK_SIZE) |
| uint8_t prepared_mark[FLASH_WRITE_BLOCK_SIZE] = {ERASED_VAL}; |
| #else |
| #error "Test not prepared to run from flash with no write-block-size property in DTS" |
| #endif |
| #endif |
| |
| static int c1_set(const char *name, size_t len, settings_read_cb read_cb, |
| void *cb_arg) |
| { |
| int rc; |
| const char *next; |
| |
| if (settings_name_steq(name, "val32", &next) && !next) { |
| rc = read_cb(cb_arg, &val32, sizeof(val32)); |
| zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback"); |
| return 0; |
| } |
| |
| return -ENOENT; |
| } |
| |
| static int c1_export(int (*export_func)(const char *name, |
| const void *value, size_t val_len)) |
| { |
| (void)export_func("hello/val32", &val32, sizeof(val32)); |
| |
| return 0; |
| } |
| |
| static struct settings_handler c1_settings = { |
| .name = "hello", |
| .h_set = c1_set, |
| .h_export = c1_export, |
| }; |
| |
| ZTEST(fcb_initialization, test_init) |
| { |
| int err; |
| uint32_t prev_int; |
| |
| val32++; |
| |
| err = settings_save(); |
| zassert_true(err == 0, "can't save settings"); |
| |
| prev_int = val32; |
| val32 = 0U; |
| err = settings_load(); |
| zassert_true(err == 0, "can't load settings"); |
| zassert_equal(prev_int, val32, |
| "load value doesn't match to what was saved"); |
| } |
| |
| |
| void test_prepare_storage(void) |
| { |
| #if CODE_PARTITION_EXISTS |
| /* This procedure uses mark which is stored inside SoC embedded program |
| * flash. It will not work on devices on which read/write to them is not |
| * possible. |
| */ |
| int err; |
| const struct flash_area *fa; |
| const struct device *dev; |
| uint8_t new_val[FLASH_WRITE_BLOCK_SIZE]; |
| |
| if (prepared_mark[0] == ERASED_VAL) { |
| TC_PRINT("First run: erasing the storage\r\n"); |
| err = flash_area_open(TEST_PARTITION_ID, &fa); |
| zassert_true(err == 0, "Can't open storage flash area"); |
| |
| err = flash_area_erase(fa, 0, fa->fa_size); |
| zassert_true(err == 0, "Can't erase storage flash area"); |
| |
| err = flash_area_open(CODE_PARTITION_ID, &fa); |
| zassert_true(err == 0, "Can't open storage flash area"); |
| |
| dev = flash_area_get_device(fa); |
| |
| (void)memset(new_val, (~ERASED_VAL) & 0xFF, |
| FLASH_WRITE_BLOCK_SIZE); |
| err = flash_write(dev, (off_t)&prepared_mark, &new_val, |
| sizeof(new_val)); |
| zassert_true(err == 0, "can't write prepared_mark"); |
| } |
| #else |
| TC_PRINT("Storage preparation can't be performed\r\n"); |
| TC_PRINT("Erase storage manually before test flashing\r\n"); |
| #endif |
| } |
| |
| void *test_init_setup(void) |
| { |
| int err; |
| |
| test_prepare_storage(); |
| |
| err = settings_subsys_init(); |
| zassert_true(err == 0, "subsys init failed"); |
| |
| err = settings_register(&c1_settings); |
| zassert_true(err == 0, "can't register the settings handler"); |
| |
| err = settings_load(); |
| zassert_true(err == 0, "can't load settings"); |
| |
| if (val32 < 1) { |
| val32 = 1U; |
| err = settings_save(); |
| zassert_true(err == 0, "can't save settings"); |
| k_sleep(K_MSEC(250)); |
| sys_reboot(SYS_REBOOT_COLD); |
| } |
| return NULL; |
| } |
| |
| ZTEST_SUITE(fcb_initialization, NULL, test_init_setup, NULL, NULL, NULL); |