1 /*
2 * Copyright (c) 2024 Ambiq Micro Inc. <www.ambiq.com>
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 #define SPI_FLASH_TEST_REGION_OFFSET 0xff000
15
16 #define SPI_FLASH_SECTOR_SIZE 4096
17
18 #define SPI_FLASH_MULTI_SECTOR_TEST
19
single_sector_test(const struct device * flash_dev)20 int single_sector_test(const struct device *flash_dev)
21 {
22 const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 };
23 const size_t len = sizeof(expected);
24 uint8_t buf[sizeof(expected)];
25 int rc;
26
27 printf("\nPerform test on single sector");
28 /* Write protection needs to be disabled before each write or
29 * erase, since the flash component turns on write protection
30 * automatically after completion of write and erase
31 * operations.
32 */
33 printf("\nTest 1: Flash erase\n");
34
35 /* Full flash erase if SPI_FLASH_TEST_REGION_OFFSET = 0 and
36 * SPI_FLASH_SECTOR_SIZE = flash size
37 */
38 rc = flash_erase(flash_dev, SPI_FLASH_TEST_REGION_OFFSET,
39 SPI_FLASH_SECTOR_SIZE);
40 if (rc != 0) {
41 printf("Flash erase failed! %d\n", rc);
42 } else {
43 printf("Flash erase succeeded!\n");
44 }
45
46 printf("\nTest 2: Flash write\n");
47
48 printf("Attempting to write %zu bytes\n", len);
49 rc = flash_write(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, expected, len);
50 if (rc != 0) {
51 printf("Flash write failed! %d\n", rc);
52 return 1;
53 }
54
55 memset(buf, 0, len);
56 rc = flash_read(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, buf, len);
57 if (rc != 0) {
58 printf("Flash read failed! %d\n", rc);
59 return 1;
60 }
61
62 if (memcmp(expected, buf, len) == 0) {
63 printf("Data read matches data written. Good!!\n");
64 } else {
65 const uint8_t *wp = expected;
66 const uint8_t *rp = buf;
67 const uint8_t *rpe = rp + len;
68
69 printf("Data read does not match data written!!\n");
70 while (rp < rpe) {
71 printf("%08x wrote %02x read %02x %s\n",
72 (uint32_t)(SPI_FLASH_TEST_REGION_OFFSET + (rp - buf)),
73 *wp, *rp, (*rp == *wp) ? "match" : "MISMATCH");
74 ++rp;
75 ++wp;
76 }
77 }
78 return rc;
79 }
80
81 #if defined SPI_FLASH_MULTI_SECTOR_TEST
multi_sector_test(const struct device * flash_dev)82 int multi_sector_test(const struct device *flash_dev)
83 {
84 const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 };
85 const size_t len = sizeof(expected);
86 uint8_t buf[sizeof(expected)];
87 int rc;
88
89 printf("\nPerform test on multiple consequtive sectors");
90
91 /* Write protection needs to be disabled before each write or
92 * erase, since the flash component turns on write protection
93 * automatically after completion of write and erase
94 * operations.
95 */
96 printf("\nTest 1: Flash erase\n");
97
98 /* Full flash erase if SPI_FLASH_TEST_REGION_OFFSET = 0 and
99 * SPI_FLASH_SECTOR_SIZE = flash size
100 * Erase 2 sectors for check for erase of consequtive sectors
101 */
102 rc = flash_erase(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, SPI_FLASH_SECTOR_SIZE * 2);
103 if (rc != 0) {
104 printf("Flash erase failed! %d\n", rc);
105 } else {
106 /* Read the content and check for erased */
107 memset(buf, 0, len);
108 size_t offs = SPI_FLASH_TEST_REGION_OFFSET;
109
110 while (offs < SPI_FLASH_TEST_REGION_OFFSET + 2 * SPI_FLASH_SECTOR_SIZE) {
111 rc = flash_read(flash_dev, offs, buf, len);
112 if (rc != 0) {
113 printf("Flash read failed! %d\n", rc);
114 return 1;
115 }
116 if (buf[0] != 0xff) {
117 printf("Flash erase failed at offset 0x%x got 0x%x\n",
118 offs, buf[0]);
119 return 1;
120 }
121 offs += SPI_FLASH_SECTOR_SIZE;
122 }
123 printf("Flash erase succeeded!\n");
124 }
125
126 printf("\nTest 2: Flash write\n");
127
128 size_t offs = SPI_FLASH_TEST_REGION_OFFSET;
129
130 while (offs < SPI_FLASH_TEST_REGION_OFFSET + 2 * SPI_FLASH_SECTOR_SIZE) {
131 printf("Attempting to write %zu bytes at offset 0x%x\n", len, offs);
132 rc = flash_write(flash_dev, offs, expected, len);
133 if (rc != 0) {
134 printf("Flash write failed! %d\n", rc);
135 return 1;
136 }
137
138 memset(buf, 0, len);
139 rc = flash_read(flash_dev, offs, buf, len);
140 if (rc != 0) {
141 printf("Flash read failed! %d\n", rc);
142 return 1;
143 }
144
145 if (memcmp(expected, buf, len) == 0) {
146 printf("Data read matches data written. Good!!\n");
147 } else {
148 const uint8_t *wp = expected;
149 const uint8_t *rp = buf;
150 const uint8_t *rpe = rp + len;
151
152 printf("Data read does not match data written!!\n");
153 while (rp < rpe) {
154 printf("%08x wrote %02x read %02x %s\n",
155 (uint32_t)(offs + (rp - buf)),
156 *wp, *rp, (*rp == *wp) ? "match" : "MISMATCH");
157 ++rp;
158 ++wp;
159 }
160 }
161 offs += SPI_FLASH_SECTOR_SIZE;
162 }
163 return rc;
164 }
165 #endif
166
main(void)167 int main(void)
168 {
169 const struct device *flash_dev = DEVICE_DT_GET(DT_ALIAS(flash0));
170
171 if (!device_is_ready(flash_dev)) {
172 printk("%s: device not ready.\n", flash_dev->name);
173 return 1;
174 }
175
176 printf("\n%s SPI flash testing\n", flash_dev->name);
177 printf("==========================\n");
178
179 if (single_sector_test(flash_dev)) {
180 return 1;
181 }
182 #if defined SPI_FLASH_MULTI_SECTOR_TEST
183 if (multi_sector_test(flash_dev)) {
184 return 1;
185 }
186 #endif
187 printf("==========================\n");
188 return 0;
189 }
190