1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/drivers/flash.h>
9 #include <zephyr/logging/log_ctrl.h>
10 #include <zephyr/pm/device.h>
11 
12 /* Set to 1 to test the chip erase functionality. Please be aware that this
13  * operation takes quite a while (it depends on the chip size, but can easily
14  * take tens of seconds).
15  * Note - erasing of the test region or whole chip is performed only when
16  *        CONFIG_SPI_FLASH_AT45_USE_READ_MODIFY_WRITE is not enabled.
17  */
18 #define ERASE_WHOLE_CHIP    0
19 
20 #define TEST_REGION_OFFSET  0xFE00
21 #define TEST_REGION_SIZE    0x400
22 
23 static uint8_t write_buf[TEST_REGION_SIZE];
24 static uint8_t read_buf[TEST_REGION_SIZE];
25 
main(void)26 int main(void)
27 {
28 	printk("DataFlash sample on %s\n", CONFIG_BOARD);
29 
30 	const struct device *const flash_dev = DEVICE_DT_GET_ONE(atmel_at45);
31 	int i;
32 	int err;
33 	uint8_t data;
34 #ifdef CONFIG_FLASH_PAGE_LAYOUT
35 	struct flash_pages_info pages_info;
36 	size_t page_count, chip_size;
37 #endif
38 
39 	if (!device_is_ready(flash_dev)) {
40 		printk("%s: device not ready.\n", flash_dev->name);
41 		return 0;
42 	}
43 
44 #ifdef CONFIG_FLASH_PAGE_LAYOUT
45 	page_count = flash_get_page_count(flash_dev);
46 	(void)flash_get_page_info_by_idx(flash_dev, 0, &pages_info);
47 	chip_size = page_count * pages_info.size;
48 	printk("Using %s, chip size: %u bytes (page: %u)\n",
49 	       flash_dev->name, chip_size, pages_info.size);
50 #endif
51 
52 	printk("Reading the first byte of the test region ... ");
53 	err = flash_read(flash_dev, TEST_REGION_OFFSET, &data, 1);
54 	if (err != 0) {
55 		printk("FAILED\n");
56 		return 0;
57 	}
58 
59 	printk("OK\n");
60 
61 	++data;
62 	printk("Preparing test content starting with 0x%02X.\n", data);
63 	for (i = 0; i < TEST_REGION_SIZE; ++i) {
64 		write_buf[i] = (uint8_t)(data + i);
65 	}
66 
67 #ifndef CONFIG_SPI_FLASH_AT45_USE_READ_MODIFY_WRITE
68 	if (ERASE_WHOLE_CHIP) {
69 #ifdef CONFIG_FLASH_PAGE_LAYOUT
70 		printk("Erasing the whole chip... ");
71 		err = flash_erase(flash_dev, 0, chip_size);
72 #else
73 		#error To full chip erase you need enable flash page layout
74 #endif
75 	} else {
76 		printk("Erasing the test region... ");
77 		err = flash_erase(flash_dev,
78 				  TEST_REGION_OFFSET, TEST_REGION_SIZE);
79 	}
80 
81 	if (err != 0) {
82 		printk("FAILED\n");
83 		return 0;
84 	}
85 
86 	printk("OK\n");
87 
88 	printk("Checking if the test region is erased... ");
89 	err = flash_read(flash_dev, TEST_REGION_OFFSET,
90 			 read_buf, TEST_REGION_SIZE);
91 	if (err != 0) {
92 		printk("FAILED\n");
93 		return 0;
94 	}
95 
96 	for (i = 0; i < TEST_REGION_SIZE; ++i) {
97 		if (read_buf[i] != 0xFF) {
98 			printk("\nERROR at read_buf[%d]: "
99 			       "expected 0x%02X, got 0x%02X\n",
100 			       i, 0xFF, read_buf[i]);
101 			return 0;
102 		}
103 	}
104 
105 	printk("OK\n");
106 #endif /* !CONFIG_SPI_FLASH_AT45_USE_READ_MODIFY_WRITE */
107 
108 	printk("Writing the first half of the test region... ");
109 	err = flash_write(flash_dev, TEST_REGION_OFFSET,
110 			  write_buf,  TEST_REGION_SIZE/2);
111 	if (err != 0) {
112 		printk("FAILED\n");
113 		return 0;
114 	}
115 
116 	printk("OK\n");
117 
118 	printk("Writing the second half of the test region... ");
119 	err = flash_write(flash_dev, TEST_REGION_OFFSET + TEST_REGION_SIZE/2,
120 			  &write_buf[TEST_REGION_SIZE/2], TEST_REGION_SIZE/2);
121 	if (err != 0) {
122 		printk("FAILED\n");
123 		return 0;
124 	}
125 
126 	printk("OK\n");
127 
128 	printk("Reading the whole test region... ");
129 	err = flash_read(flash_dev, TEST_REGION_OFFSET,
130 			 read_buf, TEST_REGION_SIZE);
131 	if (err != 0) {
132 		printk("FAILED\n");
133 		return 0;
134 	}
135 
136 	printk("OK\n");
137 
138 	printk("Checking the read content... ");
139 	for (i = 0; i < TEST_REGION_SIZE; ++i) {
140 		if (read_buf[i] != write_buf[i]) {
141 			printk("\nERROR at read_buf[%d]: "
142 			       "expected 0x%02X, got 0x%02X\n",
143 			       i, write_buf[i], read_buf[i]);
144 			return 0;
145 		}
146 	}
147 
148 	printk("OK\n");
149 
150 #if defined(CONFIG_PM_DEVICE)
151 	printk("Putting the flash device into suspended state... ");
152 	err = pm_device_action_run(flash_dev, PM_DEVICE_ACTION_SUSPEND);
153 	if (err != 0) {
154 		printk("FAILED\n");
155 		return 0;
156 	}
157 
158 	printk("OK\n");
159 #endif
160 
161 	k_sleep(K_FOREVER);
162 	return 0;
163 }
164