5 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
11 #include "dt/dt_flash_ctrl.h"
17 #include "sw/device/lib/testing/test_framework/check.h"
19 #include "flash_ctrl_regs.h"
21 #define MODULE_ID MAKE_MODULE_ID('f', 'c', 't')
23 status_t flash_ctrl_testutils_wait_for_init(
28 }
while (
status.controller_init_wip);
32 status_t flash_ctrl_testutils_wait_transaction_end(
44 uint32_t error_reg = 0;
63 status_t flash_ctrl_testutils_data_region_setup_properties(
65 uint32_t data_region, uint32_t region_size,
68 .
base = base_page_index,
69 .properties = region_properties,
73 data_region_properties));
84 status_t flash_ctrl_testutils_data_region_setup(
86 uint32_t data_region, uint32_t region_size, uint32_t *offset) {
88 .
ecc_en = kMultiBitBool4True,
89 .high_endurance_en = kMultiBitBool4False,
90 .erase_en = kMultiBitBool4True,
91 .prog_en = kMultiBitBool4True,
92 .rd_en = kMultiBitBool4True,
93 .scramble_en = kMultiBitBool4False};
94 return flash_ctrl_testutils_data_region_setup_properties(
95 flash_state, base_page_index, data_region, region_size, region_properties,
99 status_t flash_ctrl_testutils_data_region_scrambled_setup(
101 uint32_t data_region, uint32_t region_size, uint32_t *offset) {
103 .
ecc_en = kMultiBitBool4True,
104 .high_endurance_en = kMultiBitBool4False,
105 .erase_en = kMultiBitBool4True,
106 .prog_en = kMultiBitBool4True,
107 .rd_en = kMultiBitBool4True,
108 .scramble_en = kMultiBitBool4True};
109 return flash_ctrl_testutils_data_region_setup_properties(
110 flash_state, base_page_index, data_region, region_size, region_properties,
114 status_t flash_ctrl_testutils_info_region_setup_properties(
119 .
bank = bank, .page = page_id, .partition_id = partition_id};
126 if (offset != NULL) {
133 status_t flash_ctrl_testutils_info_region_setup(
135 uint32_t partition_id, uint32_t *offset) {
137 .
ecc_en = kMultiBitBool4True,
138 .high_endurance_en = kMultiBitBool4False,
139 .erase_en = kMultiBitBool4True,
140 .prog_en = kMultiBitBool4True,
141 .rd_en = kMultiBitBool4True,
142 .scramble_en = kMultiBitBool4False};
143 return flash_ctrl_testutils_info_region_setup_properties(
144 flash_state, page_id, bank, partition_id, region_properties, offset);
147 status_t flash_ctrl_testutils_info_region_scrambled_setup(
149 uint32_t partition_id, uint32_t *offset) {
151 .
ecc_en = kMultiBitBool4True,
152 .high_endurance_en = kMultiBitBool4False,
153 .erase_en = kMultiBitBool4True,
154 .prog_en = kMultiBitBool4True,
155 .rd_en = kMultiBitBool4True,
156 .scramble_en = kMultiBitBool4True};
157 return flash_ctrl_testutils_info_region_setup_properties(
158 flash_state, page_id, bank, partition_id, region_properties, offset);
161 status_t flash_ctrl_testutils_erase_page(
166 .partition_type = partition_type,
167 .partition_id = partition_id,
170 return flash_ctrl_testutils_wait_transaction_end(flash_state);
173 status_t flash_ctrl_testutils_write(
175 uint32_t partition_id,
const uint32_t *data,
182 if (byte_address & (
sizeof(uint32_t) - 1)) {
183 LOG_ERROR(
"Unaligned address 0x%x", byte_address);
184 return INVALID_ARGUMENT();
188 .partition_type = partition_type,
189 .partition_id = partition_id,
191 static_assert(FLASH_CTRL_PARAM_BYTES_PER_WORD >=
sizeof(uint32_t),
192 "flash_ctrl_testutils_write() assumes the flash word width is"
193 "greater than or equal to the bus word width.");
194 uint32_t words_written = 0;
195 uint32_t word_address = byte_address /
sizeof(uint32_t);
196 const uint32_t prog_window_size =
197 (uint32_t)FLASH_CTRL_PARAM_REG_BUS_PGM_RES_BYTES /
sizeof(uint32_t);
198 const uint32_t prog_window_mask = ~(prog_window_size - 1);
201 while (words_written < word_count) {
204 uint32_t window_limit =
205 ((word_address + prog_window_size) & prog_window_mask) - word_address;
206 uint32_t words_remaining = word_count - words_written;
207 uint32_t words_to_write =
208 (words_remaining < window_limit) ? words_remaining : window_limit;
209 transaction.byte_address = word_address *
sizeof(uint32_t);
210 transaction.word_count = words_to_write;
213 data + words_written));
214 status = flash_ctrl_testutils_wait_transaction_end(flash_state);
215 word_address += words_to_write;
216 words_written += words_to_write;
222 status_t flash_ctrl_testutils_erase_and_write_page(
224 uint32_t partition_id,
const uint32_t *data,
226 TRY(flash_ctrl_testutils_erase_page(flash_state, byte_address, partition_id,
228 TRY(flash_ctrl_testutils_write(flash_state, byte_address, partition_id, data,
229 partition_type, word_count));
235 uint32_t partition_id, uint32_t *data_out,
237 uint32_t delay_micros) {
240 .partition_type = partition_type,
241 .partition_id = partition_id,
242 .word_count = word_count};
249 return flash_ctrl_testutils_wait_transaction_end(flash_state);
252 status_t flash_ctrl_testutils_default_region_access(
254 bool erase_en,
bool scramble_en,
bool ecc_en,
bool high_endurance_en) {
256 .
rd_en = rd_en ? kMultiBitBool4True : kMultiBitBool4False,
257 .prog_en = prog_en ? kMultiBitBool4True : kMultiBitBool4False,
258 .erase_en = erase_en ? kMultiBitBool4True : kMultiBitBool4False,
259 .scramble_en = scramble_en ? kMultiBitBool4True : kMultiBitBool4False,
260 .ecc_en = ecc_en ? kMultiBitBool4True : kMultiBitBool4False,
262 high_endurance_en ? kMultiBitBool4True : kMultiBitBool4False};
265 default_properties));
270 uint32_t bank,
bool data_only) {
273 &bank_erase_enabled));
281 uint32_t byte_address =
284 data_only ? kDifFlashCtrlPartitionTypeData
285 : kDifFlashCtrlPartitionTypeInfo;
288 .partition_type = partition_type,
292 TRY(flash_ctrl_testutils_wait_transaction_end(flash_state));
295 bank_erase_enabled));
299 status_t flash_ctrl_testutils_show_faults(
303 #define LOG_IF_FIELD_SET(_struct, _field) \
304 if (_struct._field != 0) { \
305 LOG_INFO("Flash_ctrl fault status has " #_field); \
308 LOG_IF_FIELD_SET(faults, memory_properties_error);
309 LOG_IF_FIELD_SET(faults, read_error);
310 LOG_IF_FIELD_SET(faults, prog_window_error);
311 LOG_IF_FIELD_SET(faults, prog_type_error);
312 LOG_IF_FIELD_SET(faults, host_gnt_error);
313 LOG_IF_FIELD_SET(faults, register_integrity_error);
314 LOG_IF_FIELD_SET(faults, phy_integrity_error);
315 LOG_IF_FIELD_SET(faults, lifecycle_manager_error);
316 LOG_IF_FIELD_SET(faults, shadow_storage_error);
317 #undef LOG_IF_FIELD_SET