1 /*
2 * Copyright (c) 2023 Google Inc
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/drivers/flash/stm32_flash_api_extensions.h>
11 #include <zephyr/devicetree.h>
12 #include <zephyr/storage/flash_map.h>
13 #include <zephyr/sys/barrier.h>
14
15 #define TEST_AREA storage_partition
16 #define TEST_AREA_OFFSET FIXED_PARTITION_OFFSET(TEST_AREA)
17 #define TEST_AREA_SIZE FIXED_PARTITION_SIZE(TEST_AREA)
18 #define TEST_AREA_MAX (TEST_AREA_OFFSET + TEST_AREA_SIZE)
19 #define TEST_AREA_DEVICE FIXED_PARTITION_DEVICE(TEST_AREA)
20 #define TEST_AREA_DEVICE_REG DT_REG_ADDR(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(TEST_AREA)))
21
22 #define EXPECTED_SIZE 512
23
24 static const struct device *const flash_dev = TEST_AREA_DEVICE;
25
26 #if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
27 static const struct flash_parameters *flash_params;
28 static uint64_t sector_mask;
29 static uint8_t __aligned(4) expected[EXPECTED_SIZE];
30
sector_mask_from_offset(const struct device * dev,off_t offset,size_t size,uint64_t * mask)31 static int sector_mask_from_offset(const struct device *dev, off_t offset,
32 size_t size, uint64_t *mask)
33 {
34 struct flash_pages_info start_page, end_page;
35
36 if (flash_get_page_info_by_offs(dev, offset, &start_page) ||
37 flash_get_page_info_by_offs(dev, offset + size - 1, &end_page)) {
38 return -EINVAL;
39 }
40
41 *mask = ((1UL << (end_page.index + 1)) - 1) &
42 ~((1UL << start_page.index) - 1);
43
44 return 0;
45 }
46 #endif
47
flash_stm32_setup(void)48 static void *flash_stm32_setup(void)
49 {
50 #if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
51 struct flash_stm32_ex_op_sector_wp_out wp_status;
52 struct flash_stm32_ex_op_sector_wp_in wp_request;
53 uint8_t buf[EXPECTED_SIZE];
54 bool is_buf_clear = true;
55 int rc;
56 #endif
57
58 /* Check if tested region fits in flash. */
59 zassert_true((TEST_AREA_OFFSET + EXPECTED_SIZE) < TEST_AREA_MAX,
60 "Test area exceeds flash size");
61
62 zassert_true(device_is_ready(flash_dev));
63
64 #if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
65 flash_params = flash_get_parameters(flash_dev);
66
67 rc = sector_mask_from_offset(flash_dev, TEST_AREA_OFFSET, EXPECTED_SIZE,
68 §or_mask);
69 zassert_equal(rc, 0, "Cannot get sector mask");
70
71 TC_PRINT("Sector mask for offset 0x%x size 0x%x is 0x%llx\n",
72 TEST_AREA_OFFSET, EXPECTED_SIZE, sector_mask);
73
74 /* Check if region is not write protected. */
75 rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_SECTOR_WP,
76 (uintptr_t)NULL, &wp_status);
77 zassert_equal(rc, 0, "Cannot get write protect status");
78
79 TC_PRINT("Protected sectors: 0x%llx\n", wp_status.protected_mask);
80
81 /* Remove protection if needed. */
82 if (wp_status.protected_mask & sector_mask) {
83 TC_PRINT("Removing write protection\n");
84 wp_request.disable_mask = sector_mask;
85 wp_request.enable_mask = 0;
86
87 rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_SECTOR_WP,
88 (uintptr_t)&wp_request, NULL);
89 zassert_equal(rc, 0, "Cannot remove write protection");
90 }
91
92 /* Check if test region is not empty. */
93 rc = flash_read(flash_dev, TEST_AREA_OFFSET, buf, EXPECTED_SIZE);
94 zassert_equal(rc, 0, "Cannot read flash");
95
96 /* Check if flash is cleared. */
97 for (off_t i = 0; i < EXPECTED_SIZE; i++) {
98 if (buf[i] != flash_params->erase_value) {
99 is_buf_clear = false;
100 break;
101 }
102 }
103
104 if (!is_buf_clear) {
105 TC_PRINT("Test area is not empty. Clear it before continuing.\n");
106 rc = flash_erase(flash_dev, TEST_AREA_OFFSET, EXPECTED_SIZE);
107 zassert_equal(rc, 0, "Flash memory not properly erased");
108 }
109
110 /* Fill test buffer with some pattern. */
111 for (int i = 0; i < EXPECTED_SIZE; i++) {
112 expected[i] = i;
113 }
114 #endif
115
116 return NULL;
117 }
118
119 #if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
ZTEST(flash_stm32,test_stm32_write_protection)120 ZTEST(flash_stm32, test_stm32_write_protection)
121 {
122 struct flash_stm32_ex_op_sector_wp_in wp_request;
123 uint8_t buf[EXPECTED_SIZE];
124 int rc;
125
126 TC_PRINT("Enabling write protection...");
127 wp_request.disable_mask = 0;
128 wp_request.enable_mask = sector_mask;
129
130 rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_SECTOR_WP,
131 (uintptr_t)&wp_request, NULL);
132 zassert_equal(rc, 0, "Cannot enable write protection");
133 TC_PRINT("Done\n");
134
135 rc = flash_write(flash_dev, TEST_AREA_OFFSET, expected, EXPECTED_SIZE);
136 zassert_not_equal(rc, 0, "Write suceeded");
137 TC_PRINT("Write failed as expected, error %d\n", rc);
138
139 rc = flash_read(flash_dev, TEST_AREA_OFFSET, buf, EXPECTED_SIZE);
140 zassert_equal(rc, 0, "Cannot read flash");
141
142 for (off_t i = 0; i < EXPECTED_SIZE; i++) {
143 zassert_true(buf[i] == flash_params->erase_value,
144 "Buffer is not empty after write with protected "
145 "sectors");
146 }
147
148 TC_PRINT("Disabling write protection...");
149 wp_request.disable_mask = sector_mask;
150 wp_request.enable_mask = 0;
151
152 rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_SECTOR_WP,
153 (uintptr_t)&wp_request, NULL);
154 zassert_equal(rc, 0, "Cannot disable write protection");
155 TC_PRINT("Done\n");
156
157 rc = flash_write(flash_dev, TEST_AREA_OFFSET, expected, EXPECTED_SIZE);
158 zassert_equal(rc, 0, "Write failed");
159 TC_PRINT("Write suceeded\n");
160
161 rc = flash_read(flash_dev, TEST_AREA_OFFSET, buf, EXPECTED_SIZE);
162 zassert_equal(rc, 0, "Cannot read flash");
163
164 zassert_equal(memcmp(buf, expected, EXPECTED_SIZE), 0,
165 "Read data doesn't match expected data");
166 }
167 #endif
168
169 #if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
ZTEST(flash_stm32,test_stm32_readout_protection_disabled)170 ZTEST(flash_stm32, test_stm32_readout_protection_disabled)
171 {
172 struct flash_stm32_ex_op_rdp rdp_status;
173 int rc;
174
175 rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_RDP, (uintptr_t)NULL,
176 &rdp_status);
177 zassert_equal(rc, 0, "Failed to get RDP status");
178 zassert_false(rdp_status.enable, "RDP is enabled");
179 zassert_false(rdp_status.permanent, "RDP is enabled permanently");
180
181 TC_PRINT("RDP is disabled\n");
182 }
183 #endif
184
185 #ifdef CONFIG_FLASH_STM32_BLOCK_REGISTERS
186
187 #if defined(CONFIG_FLASH_STM32_WRITE_PROTECT) || defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
188 #error Block Register tests unable to run other tests, because of locked registers.
189 #endif
190
191 int flash_stm32_option_bytes_lock(const struct device *dev, bool enable);
192
flash_opt_locked(void)193 static bool flash_opt_locked(void)
194 {
195 FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
196
197 return regs->OPTCR & FLASH_OPTCR_OPTLOCK;
198 }
199
flash_cr_unlock(void)200 static void flash_cr_unlock(void)
201 {
202 FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
203
204 #ifdef CONFIG_SOC_SERIES_STM32H7X
205 regs->KEYR1 = FLASH_KEY1;
206 regs->KEYR1 = FLASH_KEY2;
207 #ifdef DUAL_BANK
208 regs->KEYR2 = FLASH_KEY1;
209 regs->KEYR2 = FLASH_KEY2;
210 #endif /* DUAL_BANK */
211 #else /* CONFIG_SOC_SERIES_STM32H7X */
212 regs->KEYR = FLASH_KEY1;
213 regs->KEYR = FLASH_KEY2;
214 #endif /* CONFIG_SOC_SERIES_STM32H7X */
215 barrier_dsync_fence_full();
216 }
217
flash_cr_is_locked(void)218 static bool flash_cr_is_locked(void)
219 {
220 FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
221
222 #ifdef CONFIG_SOC_SERIES_STM32H7X
223 return regs->CR1 & FLASH_CR_LOCK;
224 #ifdef DUAL_BANK
225 return (regs->CR1 & FLASH_CR_LOCK) && (regs->CR2 & FLASH_CR_LOCK);
226 #endif /* DUAL_BANK */
227 #else /* CONFIG_SOC_SERIES_STM32H7X */
228 return regs->CR & FLASH_CR_LOCK;
229 #endif /* CONFIG_SOC_SERIES_STM32H7X */
230 }
231
flash_cr_is_unlocked(void)232 static bool flash_cr_is_unlocked(void)
233 {
234 FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
235
236 #ifdef CONFIG_SOC_SERIES_STM32H7X
237 return !(regs->CR1 & FLASH_CR_LOCK);
238 #ifdef DUAL_BANK
239 return !((regs->CR1 & FLASH_CR_LOCK) || (regs->CR2 & FLASH_CR_LOCK));
240 #endif /* DUAL_BANK */
241 #else /* CONFIG_SOC_SERIES_STM32H7X */
242 return !(regs->CR & FLASH_CR_LOCK);
243 #endif /* CONFIG_SOC_SERIES_STM32H7X */
244 }
245
ZTEST(flash_stm32,test_stm32_block_registers)246 ZTEST(flash_stm32, test_stm32_block_registers)
247 {
248 /* Test OPT lock. */
249 TC_PRINT("Unlocking OPT\n");
250 flash_stm32_option_bytes_lock(flash_dev, false);
251 zassert_false(flash_opt_locked(), "Unable to unlock OPT");
252
253 TC_PRINT("Blocking OPT\n");
254 flash_ex_op(flash_dev, FLASH_STM32_EX_OP_BLOCK_OPTION_REG, (uintptr_t)NULL, NULL);
255
256 zassert_true(flash_opt_locked(), "Blocking OPT didn't lock OPT");
257 TC_PRINT("Try to unlock blocked OPT\n");
258 __set_FAULTMASK(1);
259 flash_stm32_option_bytes_lock(flash_dev, false);
260 /* Clear Bus Fault pending bit */
261 SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
262 barrier_dsync_fence_full();
263 __set_FAULTMASK(0);
264 zassert_true(flash_opt_locked(), "OPT unlocked after being blocked");
265
266 /* Test CR lock. */
267 zassert_true(flash_cr_is_locked(), "CR should be locked by default");
268 TC_PRINT("Unlocking CR\n");
269 flash_cr_unlock();
270 zassert_true(flash_cr_is_unlocked(), "Unable to unlock CR");
271 TC_PRINT("Blocking CR\n");
272 flash_ex_op(flash_dev, FLASH_STM32_EX_OP_BLOCK_CONTROL_REG, (uintptr_t)NULL, NULL);
273 zassert_true(flash_cr_is_locked(), "Blocking CR didn't lock CR");
274 __set_FAULTMASK(1);
275 TC_PRINT("Try to unlock blocked CR\n");
276 flash_cr_unlock();
277 /* Clear Bus Fault pending bit */
278 SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
279 barrier_dsync_fence_full();
280 __set_FAULTMASK(0);
281 /* Make sure previous write is completed. */
282 zassert_true(flash_cr_is_locked(), "CR unlocked after being blocked");
283 }
284 #endif
285
286 ZTEST_SUITE(flash_stm32, NULL, flash_stm32_setup, NULL, NULL, NULL);
287