Skip to content

Commit 42cdf72

Browse files
committed
drivers: flash: Add tests for STM32 extended operations
Introduced tests covers following features: - Write protection - enabling, disabling, confirming that it works. - Readout protection - checking current status. These features are implemented on STM32F4 boards, so we only allow these boards. Signed-off-by: Patryk Duda <[email protected]>
1 parent f8159b0 commit 42cdf72

File tree

5 files changed

+216
-0
lines changed

5 files changed

+216
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(stm32_extended_operations)
6+
7+
FILE(GLOB app_sources src/*.c)
8+
target_sources(app PRIVATE ${app_sources})
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (c) 2023 Google Inc
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
&flash0 {
8+
partitions {
9+
compatible = "fixed-partitions";
10+
#address-cells = <1>;
11+
#size-cells = <1>;
12+
13+
/* Reserve last 4KiB of flash for storage_partition. */
14+
storage_partition: partition@ff000 {
15+
label = "storage";
16+
reg = <0x000ff000 DT_SIZE_K(4)>;
17+
};
18+
};
19+
};

tests/drivers/flash/stm32/prj.conf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CONFIG_TEST=y
2+
CONFIG_ZTEST=y
3+
CONFIG_ZTEST_NEW_API=y
4+
5+
CONFIG_FLASH=y
6+
CONFIG_FLASH_EX_OP_ENABLED=y
7+
CONFIG_FLASH_STM32_READOUT_PROTECTION=y
8+
CONFIG_FLASH_STM32_WRITE_PROTECT=y
9+
CONFIG_FLASH_STM32_BLOCK_REGISTERS=y
10+
11+
CONFIG_MAIN_STACK_SIZE=2048
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
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+
14+
#define TEST_AREA storage_partition
15+
#define TEST_AREA_OFFSET FIXED_PARTITION_OFFSET(TEST_AREA)
16+
#define TEST_AREA_SIZE FIXED_PARTITION_SIZE(TEST_AREA)
17+
#define TEST_AREA_MAX (TEST_AREA_OFFSET + TEST_AREA_SIZE)
18+
#define TEST_AREA_DEVICE FIXED_PARTITION_DEVICE(TEST_AREA)
19+
20+
#define EXPECTED_SIZE 512
21+
22+
static const struct device *const flash_dev = TEST_AREA_DEVICE;
23+
static const struct flash_parameters *flash_params;
24+
static uint32_t sector_mask;
25+
static uint8_t __aligned(4) expected[EXPECTED_SIZE];
26+
27+
static int sector_mask_from_offset(const struct device *dev, off_t offset,
28+
size_t size, uint32_t *sector_mask)
29+
{
30+
struct flash_pages_info start_page, end_page;
31+
32+
if (flash_get_page_info_by_offs(dev, offset, &start_page) ||
33+
flash_get_page_info_by_offs(dev, offset + size - 1, &end_page)) {
34+
return -EINVAL;
35+
}
36+
37+
*sector_mask = ((1UL << (end_page.index + 1)) - 1) &
38+
~((1UL << start_page.index) - 1);
39+
40+
return 0;
41+
}
42+
43+
static void *flash_stm32_setup(void)
44+
{
45+
struct flash_stm32_ex_op_sector_wp_out wp_status;
46+
struct flash_stm32_ex_op_sector_wp_in wp_request;
47+
uint8_t buf[EXPECTED_SIZE];
48+
bool is_buf_clear = true;
49+
int rc;
50+
51+
/* Check if tested region fits in flash. */
52+
zassert_true((TEST_AREA_OFFSET + EXPECTED_SIZE) < TEST_AREA_MAX,
53+
"Test area exceeds flash size");
54+
55+
zassert_true(device_is_ready(flash_dev));
56+
57+
flash_params = flash_get_parameters(flash_dev);
58+
59+
rc = sector_mask_from_offset(flash_dev, TEST_AREA_OFFSET, EXPECTED_SIZE,
60+
&sector_mask);
61+
zassert_equal(rc, 0, "Cannot get sector mask");
62+
63+
TC_PRINT("Sector mask for offset 0x%x size 0x%x is 0x%x\n",
64+
TEST_AREA_OFFSET, EXPECTED_SIZE, sector_mask);
65+
66+
/* Check if region is not write protected. */
67+
rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_SECTOR_WP,
68+
(uintptr_t)NULL, &wp_status);
69+
zassert_equal(rc, 0, "Cannot get write protect status");
70+
71+
TC_PRINT("Protected sectors: 0x%x\n", wp_status.protected_mask);
72+
73+
/* Remove protection if needed. */
74+
if (wp_status.protected_mask & sector_mask) {
75+
TC_PRINT("Removing write protection\n");
76+
wp_request.disable_mask = sector_mask;
77+
78+
rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_SECTOR_WP,
79+
(uintptr_t)&wp_request, NULL);
80+
zassert_equal(rc, 0, "Cannot remove write protection");
81+
}
82+
83+
/* Check if test region is not empty. */
84+
rc = flash_read(flash_dev, TEST_AREA_OFFSET, buf, EXPECTED_SIZE);
85+
zassert_equal(rc, 0, "Cannot read flash");
86+
87+
/* Check if flash is cleared. */
88+
for (off_t i = 0; i < EXPECTED_SIZE; i++) {
89+
if (buf[i] != flash_params->erase_value) {
90+
is_buf_clear = false;
91+
break;
92+
}
93+
}
94+
95+
if (!is_buf_clear) {
96+
TC_PRINT("Test area is not empty. Clear it before continuing.\n");
97+
rc = flash_erase(flash_dev, TEST_AREA_OFFSET, EXPECTED_SIZE);
98+
zassert_equal(rc, 0, "Flash memory not properly erased");
99+
}
100+
101+
/* Fill test buffer with some pattern. */
102+
for (int i = 0; i < EXPECTED_SIZE; i++) {
103+
expected[i] = i;
104+
}
105+
106+
return NULL;
107+
}
108+
109+
ZTEST(flash_stm32, test_stm32_write_protection)
110+
{
111+
struct flash_stm32_ex_op_sector_wp_in wp_request;
112+
uint8_t buf[EXPECTED_SIZE];
113+
int rc;
114+
115+
TC_PRINT("Enabling write protection...");
116+
wp_request.disable_mask = 0;
117+
wp_request.enable_mask = sector_mask;
118+
119+
rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_SECTOR_WP,
120+
(uintptr_t)&wp_request, NULL);
121+
zassert_equal(rc, 0, "Cannot enable write protection");
122+
TC_PRINT("Done\n");
123+
124+
rc = flash_write(flash_dev, TEST_AREA_OFFSET, expected, EXPECTED_SIZE);
125+
zassert_not_equal(rc, 0, "Write suceeded");
126+
TC_PRINT("Write failed as expected, error %d\n", rc);
127+
128+
rc = flash_read(flash_dev, TEST_AREA_OFFSET, buf, EXPECTED_SIZE);
129+
zassert_equal(rc, 0, "Cannot read flash");
130+
131+
for (off_t i = 0; i < EXPECTED_SIZE; i++) {
132+
zassert_true(buf[i] == flash_params->erase_value,
133+
"Buffer is not empty after write with protected "
134+
"sectors");
135+
}
136+
137+
TC_PRINT("Disabling write protection...");
138+
wp_request.disable_mask = sector_mask;
139+
wp_request.enable_mask = 0;
140+
141+
rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_SECTOR_WP,
142+
(uintptr_t)&wp_request, NULL);
143+
zassert_equal(rc, 0, "Cannot disable write protection");
144+
TC_PRINT("Done\n");
145+
146+
rc = flash_write(flash_dev, TEST_AREA_OFFSET, expected, EXPECTED_SIZE);
147+
zassert_equal(rc, 0, "Write failed");
148+
TC_PRINT("Write suceeded\n");
149+
150+
rc = flash_read(flash_dev, TEST_AREA_OFFSET, buf, EXPECTED_SIZE);
151+
zassert_equal(rc, 0, "Cannot read flash");
152+
153+
zassert_equal(memcmp(buf, expected, EXPECTED_SIZE), 0,
154+
"Read data doesn't match expected data");
155+
}
156+
157+
ZTEST(flash_stm32, test_stm32_readout_protection_disabled)
158+
{
159+
struct flash_stm32_ex_op_rdp rdp_status;
160+
int rc;
161+
162+
rc = flash_ex_op(flash_dev, FLASH_STM32_EX_OP_RDP, (uintptr_t)NULL,
163+
&rdp_status);
164+
zassert_equal(rc, 0, "Failed to get RDP status");
165+
zassert_false(rdp_status.enable, "RDP is enabled");
166+
zassert_false(rdp_status.permanent, "RDP is enabled permanently");
167+
168+
TC_PRINT("RDP is disabled\n");
169+
}
170+
171+
ZTEST_SUITE(flash_stm32, NULL, flash_stm32_setup, NULL, NULL, NULL);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
common:
2+
tags: drivers flash
3+
tests:
4+
drivers.flash.stm32.default:
5+
platform_allow: nucleo_f429zi google_dragonclaw
6+
filter: dt_compat_enabled("st,stm32-flash-controller") and
7+
dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions")

0 commit comments

Comments
 (0)