1 /*
2  * Copyright (c) 2020-2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/drivers/flash.h>
10 #include <zephyr/devicetree.h>
11 #include <zephyr/storage/flash_map.h>
12 
13 #if defined(CONFIG_NORDIC_QSPI_NOR)
14 #define TEST_AREA_DEV_NODE DT_INST(0, nordic_qspi_nor)
15 #elif defined(CONFIG_SPI_NOR)
16 #define TEST_AREA_DEV_NODE DT_INST(0, jedec_spi_nor)
17 #else
18 #define TEST_AREA storage_partition
19 #endif
20 
21 /* TEST_AREA is only defined for configurations that rely on
22  * fixed-partition nodes.
23  */
24 #if defined(TEST_AREA)
25 #define TEST_AREA_OFFSET FIXED_PARTITION_OFFSET(TEST_AREA)
26 #define TEST_AREA_SIZE   FIXED_PARTITION_SIZE(TEST_AREA)
27 #define TEST_AREA_DEVICE FIXED_PARTITION_DEVICE(TEST_AREA)
28 
29 #if defined(CONFIG_SOC_NRF54L05) || defined(CONFIG_SOC_NRF54L10) || defined(CONFIG_SOC_NRF54L15)
30 #define TEST_FLASH_START (DT_REG_ADDR(DT_MEM_FROM_FIXED_PARTITION(DT_NODELABEL(TEST_AREA))))
31 #define TEST_FLASH_SIZE  (DT_REG_SIZE(DT_MEM_FROM_FIXED_PARTITION(DT_NODELABEL(TEST_AREA))))
32 #elif defined(CONFIG_SOC_NRF54H20)
33 #define TEST_FLASH_START (DT_REG_ADDR(DT_PARENT(DT_PARENT(DT_NODELABEL(TEST_AREA)))))
34 #define TEST_FLASH_SIZE  (DT_REG_SIZE(DT_PARENT(DT_PARENT(DT_NODELABEL(TEST_AREA)))))
35 #else
36 #error "Missing definition of TEST_FLASH_START and TEST_FLASH_SIZE for this target"
37 #endif
38 
39 #else
40 #error "Unsupported configuraiton"
41 #endif
42 
43 #define EXPECTED_SIZE 512
44 
45 #if !defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && !defined(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE)
46 #error There is no flash device enabled or it is missing Kconfig options
47 #endif
48 
49 static const struct device *const flash_dev = TEST_AREA_DEVICE;
50 static struct flash_pages_info page_info;
51 static uint8_t __aligned(4) expected[EXPECTED_SIZE];
52 
flash_driver_setup(void)53 static void *flash_driver_setup(void)
54 {
55 	int rc;
56 
57 	zassert_true(device_is_ready(flash_dev));
58 
59 	TC_PRINT("Test will run on device %s\n", flash_dev->name);
60 	TC_PRINT("TEST_AREA_OFFSET = 0x%lx\n", (unsigned long)TEST_AREA_OFFSET);
61 	TC_PRINT("TEST_AREA_SIZE   = 0x%lx\n", (unsigned long)TEST_AREA_SIZE);
62 	TC_PRINT("TEST_FLASH_START = 0x%lx\n", (unsigned long)TEST_FLASH_START);
63 	TC_PRINT("TEST_FLASH_SIZE  = 0x%lx\n", (unsigned long)TEST_FLASH_SIZE);
64 
65 	rc = flash_get_page_info_by_offs(flash_dev, TEST_AREA_OFFSET, &page_info);
66 	zassert_true(rc == 0, "flash_get_page_info_by_offs returned %d", rc);
67 	TC_PRINT("Test Page Info:\n");
68 	TC_PRINT("start_offset = 0x%lx\n", (unsigned long)page_info.start_offset);
69 	TC_PRINT("size         = 0x%lx\n", (unsigned long)page_info.size);
70 	TC_PRINT("index        = %d\n", page_info.index);
71 	TC_PRINT("===================================================================\n");
72 
73 	return NULL;
74 }
75 
ZTEST(flash_driver_negative,test_negative_flash_erase)76 ZTEST(flash_driver_negative, test_negative_flash_erase)
77 {
78 	int rc;
79 
80 #if !defined(TEST_AREA)
81 	/* Flash memory boundaries are correctly calculated
82 	 * only for storage_partition.
83 	 */
84 	ztest_test_skip();
85 #endif
86 
87 	/*  Acceptable values of erase size and offset are subject to
88 	 *  hardware-specific multiples of page size and offset.
89 	 */
90 
91 	/* Check error returned when erasing memory at wrong address (too low) */
92 	rc = flash_erase(flash_dev, (TEST_FLASH_START - page_info.size), page_info.size);
93 	zassert_true(rc < 0, "Invalid use of flash_erase returned %d", rc);
94 
95 	/* Check error returned when erasing memory at wrong address (too high) */
96 	rc = flash_erase(flash_dev, (TEST_FLASH_START + TEST_FLASH_SIZE), page_info.size);
97 	zassert_true(rc < 0, "Invalid use of flash_erase returned %d", rc);
98 
99 	/* Check error returned when erasing unaligned memory or too large chunk of memory */
100 	rc = flash_erase(flash_dev, (TEST_AREA_OFFSET + 1), (TEST_FLASH_SIZE + 1));
101 	zassert_true(rc < 0, "Invalid use of flash_erase returned %d", rc);
102 
103 	/* Erasing 0 bytes shall succeed */
104 	rc = flash_erase(flash_dev, TEST_AREA_OFFSET, 0);
105 	zassert_true(rc == 0, "flash_erase 0 bytes returned %d", rc);
106 }
107 
ZTEST(flash_driver_negative,test_negative_flash_fill)108 ZTEST(flash_driver_negative, test_negative_flash_fill)
109 {
110 	int rc;
111 	uint8_t fill_val = 0xA; /* Dummy value */
112 
113 #if !defined(TEST_AREA)
114 	/* Flash memory boundaries are correctly calculated
115 	 * only for storage_partition.
116 	 */
117 	ztest_test_skip();
118 #endif
119 
120 	/*  Erase page offset and size are constrains of paged, explicit erase devices,
121 	 *  but can be relaxed with devices without such requirement.
122 	 */
123 
124 	/* Check error returned when filling memory at wrong address (too low) */
125 	rc = flash_fill(flash_dev, fill_val, (TEST_FLASH_START - page_info.size), page_info.size);
126 	zassert_true(rc < 0, "Invalid use of flash_fill returned %d", rc);
127 
128 	/* Check error returned when filling memory at wrong address (too high) */
129 	rc = flash_fill(flash_dev, fill_val, (TEST_FLASH_START + TEST_FLASH_SIZE), page_info.size);
130 	zassert_true(rc < 0, "Invalid use of flash_fill returned %d", rc);
131 
132 	/* Check error returned when filling unaligned memory */
133 	rc = flash_fill(flash_dev, fill_val, (TEST_AREA_OFFSET + 1), page_info.size);
134 	zassert_true(rc < 0, "Invalid use of flash_fill returned %d", rc);
135 	rc = flash_fill(flash_dev, fill_val, TEST_AREA_OFFSET, (page_info.size + 1));
136 	zassert_true(rc < 0, "Invalid use of flash_fill returned %d", rc);
137 
138 	/* Filling 0 bytes shall succeed */
139 	rc = flash_fill(flash_dev, fill_val, TEST_AREA_OFFSET, 0);
140 	zassert_true(rc == 0, "flash_fill 0 bytes returned %d", rc);
141 }
142 
ZTEST(flash_driver_negative,test_negative_flash_flatten)143 ZTEST(flash_driver_negative, test_negative_flash_flatten)
144 {
145 	int rc;
146 
147 #if !defined(TEST_AREA)
148 	/* Flash memory boundaries are correctly calculated
149 	 * only for storage_partition.
150 	 */
151 	ztest_test_skip();
152 #endif
153 
154 	/*  Erase page offset and size are constrains of paged, explicit erase devices,
155 	 *  but can be relaxed with devices without such requirement.
156 	 */
157 
158 	/* Check error returned when flatten memory at wrong address (too low) */
159 	rc = flash_flatten(flash_dev, (TEST_FLASH_START - page_info.size), page_info.size);
160 	zassert_true(rc < 0, "Invalid use of flash_flatten returned %d", rc);
161 
162 	/* Check error returned when flatten memory at wrong address (too high) */
163 	rc = flash_flatten(flash_dev, (TEST_FLASH_START + TEST_FLASH_SIZE), page_info.size);
164 	zassert_true(rc < 0, "Invalid use of flash_flatten returned %d", rc);
165 
166 	/* Check error returned when flatten unaligned memory */
167 	rc = flash_flatten(flash_dev, (TEST_AREA_OFFSET + 1), page_info.size);
168 	zassert_true(rc < 0, "Invalid use of flash_flatten returned %d", rc);
169 	rc = flash_flatten(flash_dev, TEST_AREA_OFFSET, (page_info.size + 1));
170 	zassert_true(rc < 0, "Invalid use of flash_flatten returned %d", rc);
171 
172 	/* Flatten 0 bytes shall succeed */
173 	rc = flash_flatten(flash_dev, TEST_AREA_OFFSET, 0);
174 	zassert_true(rc == 0, "flash_flatten 0 bytes returned %d", rc);
175 }
176 
ZTEST(flash_driver_negative,test_negative_flash_read)177 ZTEST(flash_driver_negative, test_negative_flash_read)
178 {
179 	int rc;
180 	uint8_t read_buf[EXPECTED_SIZE];
181 
182 #if !defined(TEST_AREA)
183 	/* Flash memory boundaries are correctly calculated
184 	 * only for storage_partition.
185 	 */
186 	ztest_test_skip();
187 #endif
188 
189 	/*  All flash drivers support reads without alignment restrictions on
190 	 *  the read offset, the read size, or the destination address.
191 	 */
192 
193 	/* Check error returned when reading from a wrong address (too low) */
194 	rc = flash_read(flash_dev, (TEST_FLASH_START - page_info.size), read_buf, EXPECTED_SIZE);
195 	zassert_true(rc < 0, "Invalid use of flash_read returned %d", rc);
196 
197 	/* Check error returned when reading from a wrong address (too high) */
198 	rc = flash_read(flash_dev, (TEST_FLASH_START + TEST_FLASH_SIZE), read_buf, EXPECTED_SIZE);
199 	zassert_true(rc < 0, "Invalid use of flash_read returned %d", rc);
200 
201 	/* Check error returned when reading too many data */
202 	rc = flash_read(flash_dev, TEST_AREA_OFFSET, read_buf, (TEST_FLASH_SIZE + page_info.size));
203 	zassert_true(rc < 0, "Invalid use of flash_read returned %d", rc);
204 
205 	/* Reading 0 bytes shall succeed */
206 	rc = flash_read(flash_dev, TEST_AREA_OFFSET, read_buf, 0);
207 	zassert_true(rc == 0, "flash_read 0 bytes returned %d", rc);
208 }
209 
ZTEST(flash_driver_negative,test_negative_flash_write)210 ZTEST(flash_driver_negative, test_negative_flash_write)
211 {
212 	int rc;
213 
214 #if !defined(TEST_AREA)
215 	/* Flash memory boundaries are correctly calculated
216 	 * only for storage_partition.
217 	 */
218 	ztest_test_skip();
219 #endif
220 
221 	/*  Write size and offset must be multiples of the minimum write block size
222 	 *  supported by the driver.
223 	 */
224 
225 	/* Check error returned when writing to a wrong address (too low) */
226 	rc = flash_write(flash_dev, (TEST_FLASH_START - page_info.size), expected, page_info.size);
227 	zassert_true(rc < 0, "Invalid use of flash_write returned %d", rc);
228 
229 	/* Check error returned when writing to a wrong address (too high) */
230 	rc = flash_write(flash_dev, (TEST_FLASH_START + TEST_FLASH_SIZE), expected, page_info.size);
231 	zassert_true(rc < 0, "Invalid use of flash_write returned %d", rc);
232 
233 	/* Check error returned when writing at unaligned memory or too large chunk of memory */
234 	rc = flash_write(flash_dev, (TEST_AREA_OFFSET + 1), expected, (TEST_FLASH_SIZE + 1));
235 	zassert_true(rc < 0, "Invalid use of flash_write returned %d", rc);
236 
237 	/* Writing 0 bytes shall succeed */
238 	rc = flash_write(flash_dev, TEST_AREA_OFFSET, expected, 0);
239 	zassert_true(rc == 0, "flash_write 0 bytes returned %d", rc);
240 }
241 
242 ZTEST_SUITE(flash_driver_negative, NULL, flash_driver_setup, NULL, NULL, NULL);
243