1 /*
2 * Copyright 2025 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/drivers/flash.h>
9 #include <zephyr/devicetree.h>
10
11 #ifdef CONFIG_BOOTLOADER_MCUBOOT
12 #define TEST_FLASH_PART_NODE DT_NODELABEL(boot_partition)
13 #else
14 #define TEST_FLASH_PART_NODE DT_NODELABEL(slot1_partition)
15 #endif
16
17 #define TEST_FLASH_PART_OFFSET DT_REG_ADDR(TEST_FLASH_PART_NODE)
18 #define TEST_FLASH_PART_SIZE DT_REG_SIZE(TEST_FLASH_PART_NODE)
19
20 #define TEST_FLASH_CONTROLLER_NODE DT_MTD_FROM_FIXED_PARTITION(TEST_FLASH_PART_NODE)
21
22 #define PATTERN_SIZE 256
23
24 static const struct device *flash_controller = DEVICE_DT_GET(TEST_FLASH_CONTROLLER_NODE);
25
26 static uint8_t pattern[PATTERN_SIZE];
27
28 static const off_t test_area_offset = TEST_FLASH_PART_OFFSET;
29 static const size_t test_area_size = TEST_FLASH_PART_SIZE & ~(PATTERN_SIZE - 1);
30 static const off_t test_area_end = test_area_offset + test_area_size;
31 static const size_t number_of_slots = test_area_size / PATTERN_SIZE;
32
verify_block(off_t pos,uint8_t * expected_data,size_t size)33 static int verify_block(off_t pos, uint8_t *expected_data, size_t size)
34 {
35 uint8_t buffer[size];
36
37 if (flash_read(flash_controller, pos, buffer, size) != 0) {
38 return -EIO;
39 }
40
41 if (memcmp(expected_data, buffer, size) != 0) {
42 return -EBADMSG;
43 }
44
45 return 0;
46 }
47
flash_setup(void)48 static void *flash_setup(void)
49 {
50 bool pattern_available = true;
51
52 TC_PRINT("test_area_size = %zu MB\n", test_area_size >> 20);
53
54 /* Initialize pattern */
55 for (int i = 0; i < sizeof(pattern); i++) {
56 pattern[i] = i;
57 }
58
59 for (off_t pos = test_area_offset; pos < test_area_end; pos += PATTERN_SIZE) {
60 int res = verify_block(pos, pattern, sizeof(pattern));
61
62 if (res == -EBADMSG) {
63 pattern_available = false;
64 break;
65 } else if (res < 0) {
66 /* fail at any other errors */
67 zassert_ok(res);
68 return NULL;
69 }
70 }
71
72 if (!pattern_available) {
73 TC_PRINT("Erasing test area\n");
74 zassert_ok(flash_erase(flash_controller, TEST_FLASH_PART_OFFSET, test_area_size));
75
76 TC_PRINT("Writing pattern\n");
77 for (off_t pos = test_area_offset; pos < test_area_end; pos += PATTERN_SIZE) {
78 zassert_ok(flash_write(flash_controller, pos, pattern, sizeof(pattern)));
79 }
80 } else {
81 TC_PRINT("Pattern is already available\n");
82 }
83
84 return NULL;
85 }
86
ZTEST(flash_interface,test_sequential_read_pattern)87 ZTEST(flash_interface, test_sequential_read_pattern)
88 {
89 int amount = CONFIG_TEST_SEQUENTIAL_READ_PATTERN_AMOUNT;
90 off_t slot = 0;
91
92 zassert_not_equal(number_of_slots, 0);
93
94 for (int i = 0; i < amount; i++) {
95 if ((i & 255) == 0) {
96 TC_PRINT("Verifying pattern sequentially (%i/%i)\n", i + 1, amount);
97 }
98 zassert_ok(verify_block(test_area_offset + (slot * PATTERN_SIZE), pattern,
99 sizeof(pattern)));
100 slot = (slot + 1) % number_of_slots;
101 }
102 }
103
ZTEST(flash_interface,test_sequential_alternating_read_pattern)104 ZTEST(flash_interface, test_sequential_alternating_read_pattern)
105 {
106 int amount = CONFIG_TEST_SEQUENTIAL_ALTERNATING_READ_PATTERN_AMOUNT;
107 off_t slot1 = 0;
108 off_t slot2 = number_of_slots / 2;
109
110 zassert_not_equal(number_of_slots, 0);
111
112 for (int i = 0; i < amount; i++) {
113 if ((i & 255) == 0) {
114 TC_PRINT(
115 "Verifying pattern sequentially on alternating positions (%i/%i)\n",
116 i + 1, amount);
117 }
118 zassert_ok(verify_block(test_area_offset + (slot1 * PATTERN_SIZE), pattern,
119 sizeof(pattern)));
120 zassert_ok(verify_block(test_area_offset + (slot2 * PATTERN_SIZE), pattern,
121 sizeof(pattern)));
122 slot1 = (slot1 + 1) % number_of_slots;
123 slot2 = (slot2 + 1) % number_of_slots;
124 }
125 }
126
127 ZTEST_SUITE(flash_interface, NULL, flash_setup, NULL, NULL, NULL);
128