| /* |
| * Copyright (c) 2020 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/zephyr.h> |
| #include <ztest.h> |
| #include <zephyr/drivers/flash.h> |
| #include <zephyr/devicetree.h> |
| #include <zephyr/storage/flash_map.h> |
| |
| #if (CONFIG_NORDIC_QSPI_NOR - 0) |
| #define NORDIC_QSPI_NOR_NODE DT_INST(0, nordic_qspi_nor) |
| #define FLASH_NODEID NORDIC_QSPI_NOR_NODE |
| #define FLASH_TEST_REGION_OFFSET 0xff000 |
| |
| #if DT_NODE_HAS_PROP(NORDIC_QSPI_NOR_NODE, size_in_bytes) |
| #define TEST_AREA_MAX (DT_PROP(DT_INST(0, nordic_qspi_nor), size_in_bytes)) |
| #else |
| #define TEST_AREA_MAX (DT_PROP(DT_INST(0, nordic_qspi_nor), size) / 8) |
| #endif |
| |
| #elif defined(CONFIG_FLASH_MCUX_FLEXSPI_NOR) |
| |
| #define FLASH_NODEID DT_INST(0, nxp_imx_flexspi_nor) |
| #define FLASH_TEST_REGION_OFFSET FLASH_AREA_OFFSET(storage) |
| #define TEST_AREA_MAX ((FLASH_AREA_SIZE(storage)) + (FLASH_TEST_REGION_OFFSET)) |
| #elif defined(CONFIG_FLASH_MCUX_FLEXSPI_MX25UM51345G) |
| |
| #define FLASH_NODEID DT_INST(0, nxp_imx_flexspi_mx25um51345g) |
| #define FLASH_TEST_REGION_OFFSET FLASH_AREA_OFFSET(storage) |
| #define TEST_AREA_MAX ((FLASH_AREA_SIZE(storage)) + (FLASH_TEST_REGION_OFFSET)) |
| #else |
| |
| /* SoC embedded NVM */ |
| #define FLASH_NODEID DT_CHOSEN(zephyr_flash_controller) |
| |
| #ifdef CONFIG_TRUSTED_EXECUTION_NONSECURE |
| #define FLASH_TEST_REGION_OFFSET FLASH_AREA_OFFSET(image_1_nonsecure) |
| #define TEST_AREA_MAX (FLASH_TEST_REGION_OFFSET +\ |
| FLASH_AREA_SIZE(image_1_nonsecure)) |
| #else |
| #define FLASH_TEST_REGION_OFFSET FLASH_AREA_OFFSET(storage) |
| #define TEST_AREA_MAX (FLASH_TEST_REGION_OFFSET + FLASH_AREA_SIZE(storage)) |
| #endif |
| |
| #endif |
| |
| #define EXPECTED_SIZE 256 |
| #define CANARY 0xff |
| |
| static const struct device *flash_dev = DEVICE_DT_GET(FLASH_NODEID); |
| static struct flash_pages_info page_info; |
| static uint8_t __aligned(4) expected[EXPECTED_SIZE]; |
| |
| static void test_setup(void) |
| { |
| int rc; |
| |
| zassert_true(device_is_ready(flash_dev), NULL); |
| |
| const struct flash_parameters *flash_params = |
| flash_get_parameters(flash_dev); |
| |
| /* For tests purposes use page (in nrf_qspi_nor page = 64 kB) */ |
| flash_get_page_info_by_offs(flash_dev, FLASH_TEST_REGION_OFFSET, |
| &page_info); |
| |
| /* Check if test region is not empty */ |
| uint8_t buf[EXPECTED_SIZE]; |
| |
| rc = flash_read(flash_dev, FLASH_TEST_REGION_OFFSET, |
| buf, EXPECTED_SIZE); |
| zassert_equal(rc, 0, "Cannot read flash"); |
| |
| /* Fill test buffer with random data */ |
| for (int i = 0; i < EXPECTED_SIZE; i++) { |
| expected[i] = i; |
| } |
| |
| /* Check if tested region fits in flash */ |
| zassert_true((FLASH_TEST_REGION_OFFSET + EXPECTED_SIZE) < TEST_AREA_MAX, |
| "Test area exceeds flash size"); |
| |
| /* Check if flash is cleared */ |
| bool is_buf_clear = true; |
| |
| for (off_t i = 0; i < EXPECTED_SIZE; i++) { |
| if (buf[i] != flash_params->erase_value) { |
| is_buf_clear = false; |
| break; |
| } |
| } |
| |
| if (!is_buf_clear) { |
| /* erase page */ |
| rc = flash_erase(flash_dev, page_info.start_offset, |
| page_info.size); |
| zassert_equal(rc, 0, "Flash memory not properly erased"); |
| } |
| |
| } |
| |
| static void test_read_unaligned_address(void) |
| { |
| int rc; |
| uint8_t buf[EXPECTED_SIZE]; |
| |
| rc = flash_write(flash_dev, |
| page_info.start_offset, |
| expected, EXPECTED_SIZE); |
| zassert_equal(rc, 0, "Cannot write to flash"); |
| |
| /* read buffer length*/ |
| for (off_t len = 0; len < 25; len++) { |
| /* address offset */ |
| for (off_t ad_o = 0; ad_o < 4; ad_o++) { |
| /* buffer offset; leave space for buffer guard */ |
| for (off_t buf_o = 1; buf_o < 5; buf_o++) { |
| /* buffer overflow protection */ |
| buf[buf_o - 1] = CANARY; |
| buf[buf_o + len] = CANARY; |
| memset(buf + buf_o, 0, len); |
| rc = flash_read(flash_dev, |
| page_info.start_offset + ad_o, |
| buf + buf_o, len); |
| zassert_equal(rc, 0, "Cannot read flash"); |
| zassert_equal(memcmp(buf + buf_o, |
| expected + ad_o, |
| len), |
| 0, "Flash read failed at len=%d, " |
| "ad_o=%d, buf_o=%d", len, ad_o, buf_o); |
| /* check buffer guards */ |
| zassert_equal(buf[buf_o - 1], CANARY, |
| "Buffer underflow at len=%d, " |
| "ad_o=%d, buf_o=%d", len, ad_o, buf_o); |
| zassert_equal(buf[buf_o + len], CANARY, |
| "Buffer overflow at len=%d, " |
| "ad_o=%d, buf_o=%d", len, ad_o, buf_o); |
| } |
| } |
| } |
| } |
| |
| void test_main(void) |
| { |
| ztest_test_suite(flash_driver_test, |
| ztest_unit_test(test_setup), |
| ztest_unit_test(test_read_unaligned_address) |
| ); |
| |
| ztest_run_test_suite(flash_driver_test); |
| } |