1 /*
2 * Copyright (c) 2016 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/drivers/flash.h>
9 #include <zephyr/device.h>
10 #include <zephyr/devicetree.h>
11 #include <stdio.h>
12 #include <string.h>
13
14 #if defined(CONFIG_BOARD_ADAFRUIT_FEATHER_STM32F405)
15 #define SPI_FLASH_TEST_REGION_OFFSET 0xf000
16 #elif defined(CONFIG_BOARD_ARTY_A7_DESIGNSTART_FPGA_CORTEX_M1) || \
17 defined(CONFIG_BOARD_ARTY_A7_DESIGNSTART_FPGA_CORTEX_M3)
18 /* The FPGA bitstream is stored in the lower 536 sectors of the flash. */
19 #define SPI_FLASH_TEST_REGION_OFFSET \
20 DT_REG_SIZE(DT_NODE_BY_FIXED_PARTITION_LABEL(fpga_bitstream))
21 #elif defined(CONFIG_BOARD_NPCX9M6F_EVB) || \
22 defined(CONFIG_BOARD_NPCX7M6FB_EVB)
23 #define SPI_FLASH_TEST_REGION_OFFSET 0x7F000
24 #else
25 #define SPI_FLASH_TEST_REGION_OFFSET 0xff000
26 #endif
27 #define SPI_FLASH_SECTOR_SIZE 4096
28
29 #if defined(CONFIG_FLASH_STM32_OSPI) || \
30 defined(CONFIG_FLASH_STM32_QSPI) || \
31 defined(CONFIG_FLASH_STM32_XSPI)
32 #define SPI_FLASH_MULTI_SECTOR_TEST
33 #endif
34
35 #if DT_HAS_COMPAT_STATUS_OKAY(jedec_spi_nor)
36 #define SPI_FLASH_COMPAT jedec_spi_nor
37 #elif DT_HAS_COMPAT_STATUS_OKAY(jedec_mspi_nor)
38 #define SPI_FLASH_COMPAT jedec_mspi_nor
39 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_qspi_nor)
40 #define SPI_FLASH_COMPAT st_stm32_qspi_nor
41 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_ospi_nor)
42 #define SPI_FLASH_COMPAT st_stm32_ospi_nor
43 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_xspi_nor)
44 #define SPI_FLASH_COMPAT st_stm32_xspi_nor
45 #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_qspi_nor)
46 #define SPI_FLASH_COMPAT nordic_qspi_nor
47 #else
48 #define SPI_FLASH_COMPAT invalid
49 #endif
50
51 const uint8_t erased[] = { 0xff, 0xff, 0xff, 0xff };
52
single_sector_test(const struct device * flash_dev)53 void single_sector_test(const struct device *flash_dev)
54 {
55 const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 };
56 const size_t len = sizeof(expected);
57 uint8_t buf[sizeof(expected)];
58 int rc;
59
60 printf("\nPerform test on single sector");
61 /* Write protection needs to be disabled before each write or
62 * erase, since the flash component turns on write protection
63 * automatically after completion of write and erase
64 * operations.
65 */
66 printf("\nTest 1: Flash erase\n");
67
68 /* Full flash erase if SPI_FLASH_TEST_REGION_OFFSET = 0 and
69 * SPI_FLASH_SECTOR_SIZE = flash size
70 */
71 rc = flash_erase(flash_dev, SPI_FLASH_TEST_REGION_OFFSET,
72 SPI_FLASH_SECTOR_SIZE);
73 if (rc != 0) {
74 printf("Flash erase failed! %d\n", rc);
75 } else {
76 /* Check erased pattern */
77 memset(buf, 0, len);
78 rc = flash_read(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, buf, len);
79 if (rc != 0) {
80 printf("Flash read failed! %d\n", rc);
81 return;
82 }
83 if (memcmp(erased, buf, len) != 0) {
84 printf("Flash erase failed at offset 0x%x got 0x%x\n",
85 SPI_FLASH_TEST_REGION_OFFSET, *(uint32_t *)buf);
86 return;
87 }
88 printf("Flash erase succeeded!\n");
89 }
90 printf("\nTest 2: Flash write\n");
91
92 printf("Attempting to write %zu bytes\n", len);
93 rc = flash_write(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, expected, len);
94 if (rc != 0) {
95 printf("Flash write failed! %d\n", rc);
96 return;
97 }
98
99 memset(buf, 0, len);
100 rc = flash_read(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, buf, len);
101 if (rc != 0) {
102 printf("Flash read failed! %d\n", rc);
103 return;
104 }
105
106 if (memcmp(expected, buf, len) == 0) {
107 printf("Data read matches data written. Good!!\n");
108 } else {
109 const uint8_t *wp = expected;
110 const uint8_t *rp = buf;
111 const uint8_t *rpe = rp + len;
112
113 printf("Data read does not match data written!!\n");
114 while (rp < rpe) {
115 printf("%08x wrote %02x read %02x %s\n",
116 (uint32_t)(SPI_FLASH_TEST_REGION_OFFSET + (rp - buf)),
117 *wp, *rp, (*rp == *wp) ? "match" : "MISMATCH");
118 ++rp;
119 ++wp;
120 }
121 }
122 }
123
124 #if defined SPI_FLASH_MULTI_SECTOR_TEST
multi_sector_test(const struct device * flash_dev)125 void multi_sector_test(const struct device *flash_dev)
126 {
127 const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 };
128 const size_t len = sizeof(expected);
129 uint8_t buf[sizeof(expected)];
130 int rc;
131
132 printf("\nPerform test on multiple consecutive sectors");
133
134 /* Write protection needs to be disabled before each write or
135 * erase, since the flash component turns on write protection
136 * automatically after completion of write and erase
137 * operations.
138 */
139 printf("\nTest 1: Flash erase\n");
140
141 /* Full flash erase if SPI_FLASH_TEST_REGION_OFFSET = 0 and
142 * SPI_FLASH_SECTOR_SIZE = flash size
143 * Erase 2 sectors for check for erase of consequtive sectors
144 */
145 rc = flash_erase(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, SPI_FLASH_SECTOR_SIZE * 2);
146 if (rc != 0) {
147 printf("Flash erase failed! %d\n", rc);
148 } else {
149 /* Read the content and check for erased */
150 memset(buf, 0, len);
151 size_t offs = SPI_FLASH_TEST_REGION_OFFSET;
152
153 while (offs < SPI_FLASH_TEST_REGION_OFFSET + 2 * SPI_FLASH_SECTOR_SIZE) {
154 rc = flash_read(flash_dev, offs, buf, len);
155 if (rc != 0) {
156 printf("Flash read failed! %d\n", rc);
157 return;
158 }
159 if (memcmp(erased, buf, len) != 0) {
160 printf("Flash erase failed at offset 0x%x got 0x%x\n",
161 offs, *(uint32_t *)buf);
162 return;
163 }
164 offs += SPI_FLASH_SECTOR_SIZE;
165 }
166 printf("Flash erase succeeded!\n");
167 }
168
169 printf("\nTest 2: Flash write\n");
170
171 size_t offs = SPI_FLASH_TEST_REGION_OFFSET;
172
173 while (offs < SPI_FLASH_TEST_REGION_OFFSET + 2 * SPI_FLASH_SECTOR_SIZE) {
174 printf("Attempting to write %zu bytes at offset 0x%x\n", len, offs);
175 rc = flash_write(flash_dev, offs, expected, len);
176 if (rc != 0) {
177 printf("Flash write failed! %d\n", rc);
178 return;
179 }
180
181 memset(buf, 0, len);
182 rc = flash_read(flash_dev, offs, buf, len);
183 if (rc != 0) {
184 printf("Flash read failed! %d\n", rc);
185 return;
186 }
187
188 if (memcmp(expected, buf, len) == 0) {
189 printf("Data read matches data written. Good!!\n");
190 } else {
191 const uint8_t *wp = expected;
192 const uint8_t *rp = buf;
193 const uint8_t *rpe = rp + len;
194
195 printf("Data read does not match data written!!\n");
196 while (rp < rpe) {
197 printf("%08x wrote %02x read %02x %s\n",
198 (uint32_t)(offs + (rp - buf)),
199 *wp, *rp, (*rp == *wp) ? "match" : "MISMATCH");
200 ++rp;
201 ++wp;
202 }
203 }
204 offs += SPI_FLASH_SECTOR_SIZE;
205 }
206 }
207 #endif
208
main(void)209 int main(void)
210 {
211 const struct device *flash_dev = DEVICE_DT_GET_ONE(SPI_FLASH_COMPAT);
212
213 if (!device_is_ready(flash_dev)) {
214 printk("%s: device not ready.\n", flash_dev->name);
215 return 0;
216 }
217
218 printf("\n%s SPI flash testing\n", flash_dev->name);
219 printf("==========================\n");
220
221 single_sector_test(flash_dev);
222 #if defined SPI_FLASH_MULTI_SECTOR_TEST
223 multi_sector_test(flash_dev);
224 #endif
225 return 0;
226 }
227