diff --git a/TESTS/mbed_hal/qspi/flash_configs/MX25R6435F_config.h b/TESTS/mbed_hal/qspi/flash_configs/MX25R6435F_config.h new file mode 100644 index 0000000000..80e68f007b --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/MX25R6435F_config.h @@ -0,0 +1,109 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_QSPI_FLASH_MX25R6435F_H +#define MBED_QSPI_FLASH_MX25R6435F_H + + +#define QSPI_FLASH_CHIP_STRING "MX25R6435F" + +// Command for reading status register +#define QSPI_CMD_RDSR 0x05 +// Command for reading configuration register +#define QSPI_CMD_RDCR 0x15 +// Command for writing status/configuration register +#define QSPI_CMD_WRSR 0x01 +// Command for reading security register +#define QSPI_CMD_RDSCUR 0x2B + +// Command for setting Reset Enable +#define QSPI_CMD_RSTEN 0x66 +// Command for setting Reset +#define QSPI_CMD_RST 0x99 + +// Command for setting write enable +#define QSPI_CMD_WREN 0x06 +// Command for setting write disable +#define QSPI_CMD_WRDI 0x04 + +// WRSR operations max time [us] (datasheet max time + 15%) +#define QSPI_WRSR_MAX_TIME 34500 // 30ms +// general wait max time [us] +#define QSPI_WAIT_MAX_TIME 10000 // 100ms + + +// Commands for writing (page programming) +#define QSPI_CMD_WRITE_1IO 0x02 // 1-1-1 mode +#define QSPI_CMD_WRITE_4IO 0x38 // 1-4-4 mode + +// write operations max time [us] (datasheet max time + 15%) +#define QSPI_PAGE_PROG_MAX_TIME 11500 // 10ms + +#define QSPI_PAGE_SIZE 256 // 256B + +// Commands for reading +#define QSPI_CMD_READ_1IO_FAST 0x0B // 1-1-1 mode +#define QSPI_CMD_READ_1IO 0x03 // 1-1-1 mode +#define QSPI_CMD_READ_2IO 0xBB // 1-2-2 mode +#define QSPI_CMD_READ_1I2O 0x3B // 1-1-2 mode +#define QSPI_CMD_READ_4IO 0xEB // 1-4-4 mode +#define QSPI_CMD_READ_1I4O 0x6B // 1-1-4 mode + +#define QSPI_READ_1IO_DUMMY_CYCLE 0 +#define QSPI_READ_FAST_DUMMY_CYCLE 8 +#define QSPI_READ_2IO_DUMMY_CYCLE 4 +#define QSPI_READ_1I2O_DUMMY_CYCLE 8 +#define QSPI_READ_4IO_DUMMY_CYCLE 6 +#define QSPI_READ_1I4O_DUMMY_CYCLE 8 + +// Commands for erasing +#define QSPI_CMD_ERASE_SECTOR 0x20 // 4kB +#define QSPI_CMD_ERASE_BLOCK_32 0x52 // 32kB +#define QSPI_CMD_ERASE_BLOCK_64 0xD8 // 64kB +#define QSPI_CMD_ERASE_CHIP 0x60 // or 0xC7 + +// erase operations max time [us] (datasheet max time + 15%) +#define QSPI_ERASE_SECTOR_MAX_TIME 276000 // 240 ms +#define QSPI_ERASE_BLOCK_32_MAX_TIME 3000000 // 3s +#define QSPI_ERASE_BLOCK_64_MAX_TIME 3500000 // 3.5s + +// max frequency for basic rw operation +#define QSPI_COMMON_MAX_FREQUENCY 32000000 + +#define QSPI_STATUS_REGISTER_SIZE 1 +#define QSPI_CONFIGURATION_REGISTER_SIZE 2 +#define QSPI_SECURITY_REGISTER_SIZE 1 + +// status register +#define STATUS_BIT_WIP (1 << 0) // write in progress bit +#define STATUS_BIT_WEL (1 << 1) // write enable latch +#define STATUS_BIT_BP0 (1 << 2) // +#define STATUS_BIT_BP1 (1 << 3) // +#define STATUS_BIT_BP2 (1 << 4) // +#define STATUS_BIT_BP3 (1 << 5) // +#define STATUS_BIT_QE (1 << 6) // Quad Enable +#define STATUS_BIT_SRWD (1 << 7) // status register write protect + +// configuration register 0 +// bit 0, 1, 2, 4, 5, 7 reserved +#define CONFIG0_BIT_TB (1 << 3) // Top/Bottom area protect +#define CONFIG0_BIT_DC (1 << 6) // Dummy Cycle + +// configuration register 1 +// bit 0, 2, 3, 4, 5, 6, 7 reserved +#define CONFIG1_BIT_LH (1 << 1) // 0 = Ultra Low power mode, 1 = High performance mode + + +#endif // MBED_QSPI_FLASH_MX25R6435F_H diff --git a/TESTS/mbed_hal/qspi/flash_configs/NORDIC/NRF52840_DK/flash_config.h b/TESTS/mbed_hal/qspi/flash_configs/NORDIC/NRF52840_DK/flash_config.h new file mode 100644 index 0000000000..ed288ba50a --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/NORDIC/NRF52840_DK/flash_config.h @@ -0,0 +1,33 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_QSPI_FLASH_CONFIG_H +#define MBED_QSPI_FLASH_CONFIG_H + +#include "../../MX25R6435F_config.h" + +// NRF doesn't uses read/write opcodes, instead it uses commands id's. +// Before sending it to H/W opcodes are mapped to id's in Mbed hal qspi implementation +// +// for more details see: +// targets\TARGET_NORDIC\TARGET_NRF5x\TARGET_SDK_14_2\device\nrf52840_bitfields.h +// targets\TARGET_NORDIC\TARGET_NRF5x\qspi_api.c + +// NRF doesn't support read 1IO (opcode 0x03) +#undef QSPI_CMD_READ_1IO +#define QSPI_CMD_READ_1IO QSPI_CMD_READ_1IO_FAST + + +#endif // MBED_QSPI_FLASH_CONFIG_H diff --git a/TESTS/mbed_hal/qspi/flash_configs/STM/DISCO_L475VG_IOT01A/flash_config.h b/TESTS/mbed_hal/qspi/flash_configs/STM/DISCO_L475VG_IOT01A/flash_config.h new file mode 100644 index 0000000000..69392426c4 --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/STM/DISCO_L475VG_IOT01A/flash_config.h @@ -0,0 +1,26 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_QSPI_FLASH_CONFIG_H +#define MBED_QSPI_FLASH_CONFIG_H + +#include "../../MX25R6435F_config.h" + +// TODO: remove when fixed +// when perform 4IO write, when memory indicates write finish (changing WIP bit in status register) +// but actually write is still in progress and we have to wait a bit more before reading +#define STM_DISCO_L475VG_IOT01A_WRITE_4IO_BUG_WORKAROUND + +#endif // MBED_QSPI_FLASH_CONFIG_H diff --git a/TESTS/mbed_hal/qspi/flash_configs/flash_configs.h b/TESTS/mbed_hal/qspi/flash_configs/flash_configs.h new file mode 100644 index 0000000000..9f2ca0ef55 --- /dev/null +++ b/TESTS/mbed_hal/qspi/flash_configs/flash_configs.h @@ -0,0 +1,26 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_FLASH_CONFIGS_H +#define MBED_FLASH_CONFIGS_H + +#if defined(TARGET_DISCO_L475VG_IOT01A) +#include "STM/DISCO_L475VG_IOT01A/flash_config.h" +#elif defined(TARGET_NRF52840) +#include "NORDIC/NRF52840_DK/flash_config.h" +#endif + +#endif // MBED_FLASH_CONFIGS_H diff --git a/TESTS/mbed_hal/qspi/main.cpp b/TESTS/mbed_hal/qspi/main.cpp new file mode 100644 index 0000000000..62b029d971 --- /dev/null +++ b/TESTS/mbed_hal/qspi/main.cpp @@ -0,0 +1,409 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !DEVICE_QSPI +#error [NOT_SUPPORTED] test not supported +#endif + +#include "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" +#include "qspi_test.h" +#include "qspi_test_utils.h" + +#include "mbed.h" +#include "qspi_api.h" + + +using namespace utest::v1; + +// uncomment to enable verbose mode +//#define QSPI_TEST_LOG_DATA +//#define QSPI_TEST_LOG_FLASH_TIME +//#define QSPI_TEST_LOG_FLASH_STATUS + + +// max write size is usually page size +#define DATA_SIZE_256 (QSPI_PAGE_SIZE) +#define DATA_SIZE_1024 (QSPI_PAGE_SIZE * 4) + +uint8_t tx_buf[DATA_SIZE_1024]; +uint8_t rx_buf[DATA_SIZE_1024]; + + +// write address should be page aligned +#define TEST_FLASH_ADDRESS 0x0 + +#define TEST_REPEAT_SINGLE 1 +#define TEST_REPEAT_MULTIPLE 16 + +// write block of data in single write operation +#define WRITE_SINGLE 1 +// write block of data in adjacent locations in multiple write operations +#define WRITE_MULTIPLE 4 + +// read block of data in single read operation +#define READ_SINGLE 1 +// read block of data in adjacent locations in multiple read operations +#define READ_MULTIPLE 4 + + +// some target defines QSPI pins as integers thus conversion needed +#define QPIN_0 static_cast(QSPI_PIN_IO0) +#define QPIN_1 static_cast(QSPI_PIN_IO1) +#define QPIN_2 static_cast(QSPI_PIN_IO2) +#define QPIN_3 static_cast(QSPI_PIN_IO3) +#define QSCK static_cast(QSPI_PIN_SCK) +#define QCSN static_cast(QSPI_PIN_CSN) + + +static void log_data(const char *str, uint8_t *data, uint32_t size) +{ + printf("%s: ", str); + for (uint32_t j = 0; j < size; j++) { + printf("%02X ", data[j]); + } + printf("\r\n"); +} + + +static void _qspi_write_read_test(Qspi &qspi, qspi_bus_width_t write_inst_width, qspi_bus_width_t write_addr_width, + qspi_bus_width_t write_data_width, qspi_bus_width_t write_alt_width, uint32_t write_cmd, + qspi_address_size_t write_addr_size, qspi_alt_size_t write_alt_size, int write_frequency, + uint32_t write_count, qspi_bus_width_t read_inst_width, qspi_bus_width_t read_addr_width, + qspi_bus_width_t read_data_width, qspi_bus_width_t read_alt_width, uint32_t read_cmd, + int read_dummy_cycles, qspi_address_size_t read_addr_size, qspi_alt_size_t read_alt_size, + int read_frequency, uint32_t read_count, uint32_t test_count, uint32_t data_size, + uint32_t flash_addr) +{ + qspi_status_t ret = QSPI_STATUS_OK; + + Timer timer; + int erase_time, write_time, read_time; + size_t buf_len = data_size; + + for (uint32_t tc = 0; tc < test_count; tc++) + { + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + + srand (ticker_read(get_us_ticker_data())); + for(uint32_t i = 0; i < data_size; i++) { + tx_buf[i] = (uint8_t)(rand() & 0xFF); + } + + ret = write_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + timer.reset(); + timer.start(); + + ret = erase(SECTOR_ERASE, flash_addr, qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(SECTOR_ERASE_MAX_TIME, qspi); + + timer.stop(); + erase_time = timer.read_us(); + + if (write_frequency != QSPI_NONE) { + qspi_frequency(&qspi.handle, write_frequency); + WAIT_FOR(WAIT_MAX_TIME, qspi); + } + + const uint32_t write_size = data_size / write_count; + qspi.cmd.configure(write_inst_width, write_addr_width, write_data_width, write_alt_width, write_addr_size, write_alt_size); + for (uint32_t wc = 0, write_start = flash_addr; wc < write_count; wc++, write_start += write_size) + { + ret = write_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + timer.reset(); + timer.start(); + + buf_len = write_size; + qspi.cmd.build(write_cmd, write_start); + ret = qspi_write(&qspi.handle, qspi.cmd.get(), tx_buf + wc * write_size, &buf_len); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + TEST_ASSERT_EQUAL(write_size, buf_len); + WAIT_FOR(PAGE_PROG_MAX_TIME, qspi); + + timer.stop(); + write_time = timer.read_us(); +#ifdef STM_DISCO_L475VG_IOT01A_WRITE_4IO_BUG_WORKAROUND + if (write_cmd == QSPI_CMD_WRITE_4IO) { + wait_us(2000); + } +#endif + } + + if (read_frequency != QSPI_NONE) { + qspi_frequency(&qspi.handle, read_frequency); + WAIT_FOR(WAIT_MAX_TIME, qspi); + } + + memset(rx_buf, 0, sizeof(rx_buf)); + const uint32_t read_size = data_size / read_count; + qspi.cmd.configure(read_inst_width, read_addr_width, read_data_width, read_alt_width, read_addr_size, read_alt_size, read_dummy_cycles); + for (uint32_t rc = 0, read_start = flash_addr; rc < read_count; rc++, read_start += read_size) + { + timer.reset(); + timer.start(); + + buf_len = read_size; + qspi.cmd.build(read_cmd, read_start); + ret = qspi_read(&qspi.handle, qspi.cmd.get(), rx_buf + rc * read_size, &buf_len); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + TEST_ASSERT_EQUAL(read_size, buf_len); + + timer.stop(); + read_time = timer.read_us(); + } + + for (uint32_t i = 0; i < data_size; i++) { + if (tx_buf[i] != rx_buf[i]) { + log_data("tx data", tx_buf, data_size); + log_data("rx data", rx_buf, data_size); + printf("erase/write/read time: %d/%d/%d [us]\r\n", erase_time, write_time, read_time); + TEST_ASSERT_EQUAL(tx_buf[i], rx_buf[i]); + } + } + +#ifdef QSPI_TEST_LOG_FLASH_TIME + printf("erase/write/read time: %d/%d/%d [us]\r\n", erase_time, write_time, read_time); +#endif + +#ifdef QSPI_TEST_LOG_DATA + log_data("tx data", tx_buf, data_size); + log_data("rx data", rx_buf, data_size); + printf("rx/tx data match\r\n"); +#endif + } +} + + +template < qspi_bus_width_t write_inst_width, + qspi_bus_width_t write_addr_width, + qspi_bus_width_t write_data_width, + qspi_bus_width_t write_alt_width, + unsigned int write_cmd, + qspi_address_size_t write_addr_size, + qspi_alt_size_t write_alt_size, + int write_frequency, + uint32_t write_count, + qspi_bus_width_t read_inst_width, + qspi_bus_width_t read_addr_width, + qspi_bus_width_t read_data_width, + qspi_bus_width_t read_alt_width, + unsigned int read_cmd, + int read_dummy_cycles, + qspi_address_size_t read_addr_size, + qspi_alt_size_t read_alt_size, + int read_frequency, + uint32_t read_count, + uint32_t test_count, + uint32_t data_size, + uint32_t flash_addr> +void qspi_write_read_test(void) +{ + qspi_status_t ret; + Qspi qspi; + qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0); + + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + flash_init(qspi); + + ret = write_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(WRSR_MAX_TIME, qspi); + ret = dual_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(WRSR_MAX_TIME, qspi); + + ret = write_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(WRSR_MAX_TIME, qspi); + ret = quad_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(WRSR_MAX_TIME, qspi); + + ret = write_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(WRSR_MAX_TIME, qspi); + ret = fast_mode_enable(qspi); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + WAIT_FOR(WRSR_MAX_TIME, qspi); + +#ifdef QSPI_TEST_LOG_FLASH_STATUS + log_status_register(qspi); + log_config_register(qspi); +#endif + + _qspi_write_read_test(qspi, write_inst_width, write_addr_width, write_data_width, write_alt_width, write_cmd, + write_addr_size, write_alt_size, write_frequency, write_count, read_inst_width, + read_addr_width, read_data_width, read_alt_width, read_cmd, read_dummy_cycles, + read_addr_size, read_alt_size, read_frequency, read_count, test_count, + data_size, flash_addr); + + qspi_free(&qspi.handle); +} + + + + + +void qspi_init_free_test(void) +{ + Qspi qspi; + qspi_status_t ret; + + ret = qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + ret = qspi_free(&qspi.handle); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + + ret = qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + ret = qspi_free(&qspi.handle); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + + ret = qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + ret = qspi_free(&qspi.handle); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + + ret = qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + // check if the memory is working properly + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + flash_init(qspi); + _qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS); + qspi_free(&qspi.handle); +} + + +void qspi_frequency_test(void) +{ + Qspi qspi; + qspi_status_t ret; + + ret = qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + ret = qspi_frequency(&qspi.handle, QSPI_COMMON_MAX_FREQUENCY); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + // check if the memory is working properly + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + flash_init(qspi); + _qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS); + + ret = qspi_frequency(&qspi.handle, QSPI_COMMON_MAX_FREQUENCY/2); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + // check if the memory is working properly + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + flash_init(qspi); + _qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS); + + ret = qspi_frequency(&qspi.handle, QSPI_COMMON_MAX_FREQUENCY/4); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + // check if the memory is working properly + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + flash_init(qspi); + _qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS); + + ret = qspi_frequency(&qspi.handle, QSPI_COMMON_MAX_FREQUENCY/8); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + // check if the memory is working properly + qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); + flash_init(qspi); + _qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS); + + qspi_free(&qspi.handle); +} + + +void qspi_memory_id_test() +{ + printf("*** %s memory config loaded ***\r\n", QSPI_FLASH_CHIP_STRING); +} + + +Case cases[] = { + Case("qspi memory id test", qspi_memory_id_test), + Case("qspi init/free test", qspi_init_free_test), + Case("qspi frequency setting test", qspi_frequency_test), + // read/x1 write/x1 - read/write block of data in single write/read operation + // read/x4 write/x4 - read/write block of data in adjacent locations in multiple write/read operations + // repeat/xN - test repeat count (new data pattern each time) + Case("qspi write(1-1-1)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-1)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-2)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-2-2)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-1-4)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-1-1)/x1 read(1-4-4)/x1 repeat/x16 test", qspi_write_read_test), +#ifdef QSPI_CMD_WRITE_4IO + Case("qspi write(1-4-4)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-1)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-2)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-2-2)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-1-4)/x1 repeat/x16 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test), + Case("qspi write(1-4-4)/x1 read(1-4-4)/x1 repeat/x16 test", qspi_write_read_test), +#endif +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(120, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + Harness::run(specification); +} + diff --git a/TESTS/mbed_hal/qspi/qspi_test.h b/TESTS/mbed_hal/qspi/qspi_test.h new file mode 100644 index 0000000000..9ab3076d74 --- /dev/null +++ b/TESTS/mbed_hal/qspi/qspi_test.h @@ -0,0 +1,98 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** \addtogroup hal_qspi_tests + * @{ + */ +#ifndef MBED_QSPI_TEST_H +#define MBED_QSPI_TEST_H + +#include "qspi_api.h" +#include "qspi_test_utils.h" + + +#if DEVICE_QSPI + +/** Test that qspi_init/qspi_free can be called multiple times. + * + * Given board provides QSPI. + * When qspi_init/qspi_free is called multiple times. + * Then qspi_init/qspi_free are successfully performed (no exception is generated). + * + */ +void qspi_init_free_test(void); + +/** Test qspi frequency setting. + * + * Given board provides QSPI, with QSPI already initialized. + * When set QSPI frequency. + * Then freguency setting is successfully performed (no exception is generated). + * + */ +void qspi_frequency_test(void); + +/** Template for write/read tests + * + * Test single write/read operation of a block of data to/from the specific memory address + * Given board provides QSPI, with QSPI already initialized. + * When perform write and then read operations. + * Then data is successfully written and then read (no exception is generated) and the read data is valid. + * + * Test multiple write/read operation of a block of data to/from the same specific memory address + * Given board provides QSPI, with QSPI already initialized. + * When perform write and then read operations. + * Then data is successfully written and then read (no exception is generated) and the read data is valid. + * + * Test multiple adjacent write and single read operation of a block of data to/from the specific memory address + * Given board provides QSPI, with QSPI already initialized. + * When perform write and then read operations. + * Then data is successfully written and then read (no exception is generated) and the read data is valid. + * + * Test single write and multiple adjacent read operation of a block of data to/from the specific memory address + * Given board provides QSPI, with QSPI already initialized. + * When perform write and then read operations. + * Then data is successfully written and then read (no exception is generated) and the read data is valid. + * + */ +template < qspi_bus_width_t write_inst_width, + qspi_bus_width_t write_addr_width, + qspi_bus_width_t write_data_width, + qspi_bus_width_t write_alt_width, + unsigned int write_cmd, + qspi_address_size_t write_addr_size, + qspi_alt_size_t write_alt_size, + int write_frequency, + uint32_t write_count, + qspi_bus_width_t read_inst_width, + qspi_bus_width_t read_addr_width, + qspi_bus_width_t read_data_width, + qspi_bus_width_t read_alt_width, + unsigned int read_cmd, + int read_dummy_cycles, + qspi_address_size_t read_addr_size, + qspi_alt_size_t read_alt_size, + int read_frequency, + uint32_t read_count, + uint32_t test_count, + uint32_t data_size, + uint32_t flash_addr> +void qspi_write_read_test(void); + +#endif + +#endif + +/** @}*/ diff --git a/TESTS/mbed_hal/qspi/qspi_test_utils.cpp b/TESTS/mbed_hal/qspi/qspi_test_utils.cpp new file mode 100644 index 0000000000..83991b3a5f --- /dev/null +++ b/TESTS/mbed_hal/qspi/qspi_test_utils.cpp @@ -0,0 +1,232 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "hal/qspi_api.h" +#include "qspi_test_utils.h" + +#include "unity/unity.h" + +#include // for memset + +#include "flash_configs/flash_configs.h" +#include "mbed.h" // for WEAK + +//==================================================================================== +// all WEAK functions can be overridden, to fit board or memory chip specific features +// override in flash_configs/vendor/target/qspi_test_utils_specific.cpp +//==================================================================================== + + +void QspiCommand::configure(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, + qspi_bus_width_t data_width, qspi_bus_width_t alt_width, + qspi_address_size_t addr_size, qspi_alt_size_t alt_size, + int dummy_cycles) +{ + memset(&cmd, 0, sizeof(qspi_command_t) ); + cmd.instruction.disabled = cmd.address.disabled = cmd.alt.disabled = true; + + cmd.instruction.bus_width = inst_width; + cmd.address.bus_width = addr_width; + cmd.address.size = addr_size; + cmd.alt.bus_width = alt_width; + cmd.alt.size = alt_size; + cmd.data.bus_width = data_width; + cmd.dummy_count = dummy_cycles; +} + +void QspiCommand::build(int instruction, int address, int alt) +{ + cmd.instruction.disabled = (instruction == QSPI_NONE); + if (!cmd.instruction.disabled) { + cmd.instruction.value = instruction; + } + + cmd.address.disabled = (address == QSPI_NONE); + if (!cmd.address.disabled) { + cmd.address.value = address; + } + + cmd.alt.disabled = (alt == QSPI_NONE); + if (!cmd.alt.disabled) { + cmd.alt.value = alt; + } +} + +qspi_command_t* QspiCommand::get() +{ + return &cmd; +} + + +qspi_status_t read_register(uint32_t cmd, uint8_t *buf, uint32_t size, Qspi &q) +{ + q.cmd.build(cmd); + return qspi_command_transfer(&q.handle, q.cmd.get(), NULL, 0, buf, size); +} + + +bool flash_wait_for(uint32_t time_us, Qspi &qspi) +{ + uint8_t reg[QSPI_STATUS_REGISTER_SIZE]; + qspi_status_t ret; + reg[0] = STATUS_BIT_WIP; + + const ticker_data_t *const ticker = get_us_ticker_data(); + const uint32_t start = ticker_read(ticker); + + do { + ret = read_register(STATUS_REG, reg, QSPI_STATUS_REGISTER_SIZE, qspi); + } while (((reg[0] & STATUS_BIT_WIP) != 0) && ((ticker_read(ticker) - start) < (uint32_t)time_us)); + + return (((reg[0] & STATUS_BIT_WIP) == 0) && (ret == QSPI_STATUS_OK)); +} + +void flash_init(Qspi &qspi) +{ + uint8_t status[2] = { 0 }; + qspi_status_t ret; + + qspi.cmd.build(QSPI_CMD_RDSR); + ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, status, 1); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + WAIT_FOR(WRSR_MAX_TIME, qspi); + + qspi.cmd.build(QSPI_CMD_RSTEN); + ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + WAIT_FOR(WRSR_MAX_TIME, qspi); + + qspi.cmd.build(QSPI_CMD_RST); + ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0); + TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret); + + WAIT_FOR(WAIT_MAX_TIME, qspi); +} + + +qspi_status_t write_enable(Qspi &qspi) +{ + uint8_t reg[QSPI_STATUS_REGISTER_SIZE]; + qspi.cmd.build(QSPI_CMD_WREN); + + if (qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + WAIT_FOR(WRSR_MAX_TIME, qspi); + + memset(reg, 0, QSPI_STATUS_REGISTER_SIZE); + if (read_register(STATUS_REG, reg, QSPI_STATUS_REGISTER_SIZE, qspi) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + + return ((reg[0] & STATUS_BIT_WEL) != 0 ? QSPI_STATUS_OK : QSPI_STATUS_ERROR); +} + +qspi_status_t write_disable(Qspi &qspi) +{ + uint8_t reg[QSPI_STATUS_REGISTER_SIZE]; + qspi.cmd.build(QSPI_CMD_WRDI); + + if (qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + WAIT_FOR(WRSR_MAX_TIME, qspi); + + memset(reg, 0, QSPI_STATUS_REGISTER_SIZE); + if (read_register(STATUS_REG, reg, QSPI_STATUS_REGISTER_SIZE, qspi) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + + return ((reg[0] & STATUS_BIT_WEL) == 0 ? QSPI_STATUS_OK : QSPI_STATUS_ERROR); +} + +WEAK qspi_status_t dual_enable(Qspi &qspi) +{ + return QSPI_STATUS_OK; +} + +WEAK qspi_status_t dual_disable(Qspi &qspi) +{ + return QSPI_STATUS_OK; +} + +WEAK qspi_status_t quad_enable(Qspi &qspi) +{ + uint8_t reg_data[QSPI_STATUS_REGISTER_SIZE]; + + reg_data[0] = STATUS_BIT_QE; + qspi.cmd.build(QSPI_CMD_WRSR); + + if (qspi_command_transfer(&qspi.handle, qspi.cmd.get(), reg_data, QSPI_STATUS_REGISTER_SIZE, NULL, 0) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + WAIT_FOR(WRSR_MAX_TIME, qspi); + + memset(reg_data, 0, QSPI_STATUS_REGISTER_SIZE); + if (read_register(STATUS_REG, reg_data, QSPI_STATUS_REGISTER_SIZE, qspi) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + + return ((reg_data[0] & STATUS_BIT_QE) != 0 ? QSPI_STATUS_OK : QSPI_STATUS_ERROR); +} + +WEAK qspi_status_t quad_disable(Qspi &qspi) +{ + uint8_t reg_data[QSPI_STATUS_REGISTER_SIZE]; + + reg_data[0] = 0; + qspi.cmd.build(QSPI_CMD_WRSR); + + if (qspi_command_transfer(&qspi.handle, qspi.cmd.get(), reg_data, QSPI_STATUS_REGISTER_SIZE, NULL, 0) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + WAIT_FOR(WRSR_MAX_TIME, qspi); + + reg_data[0] = 0; + if (read_register(STATUS_REG, reg_data, QSPI_STATUS_REGISTER_SIZE, qspi) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + + return ((reg_data[0] & STATUS_BIT_QE) == 0 ? QSPI_STATUS_OK : QSPI_STATUS_ERROR); +} + +WEAK qspi_status_t fast_mode_enable(Qspi &qspi) +{ + qspi_status_t ret; + const int32_t reg_size = QSPI_STATUS_REGISTER_SIZE + QSPI_CONFIGURATION_REGISTER_SIZE; + uint8_t reg_data[reg_size]; + + if (read_register(STATUS_REG, reg_data, QSPI_STATUS_REGISTER_SIZE, qspi) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + if (read_register(CONFIG_REG, reg_data + QSPI_STATUS_REGISTER_SIZE, QSPI_CONFIGURATION_REGISTER_SIZE, qspi) != QSPI_STATUS_OK) { + return QSPI_STATUS_ERROR; + } + + reg_data[2] |= CONFIG1_BIT_LH; + qspi.cmd.build(QSPI_CMD_WRSR); + + return qspi_command_transfer(&qspi.handle, qspi.cmd.get(), reg_data, reg_size, NULL, 0); +} + +qspi_status_t erase(uint32_t erase_cmd, uint32_t flash_addr, Qspi &qspi) +{ + qspi.cmd.build(erase_cmd, flash_addr); + return qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0); +} diff --git a/TESTS/mbed_hal/qspi/qspi_test_utils.h b/TESTS/mbed_hal/qspi/qspi_test_utils.h new file mode 100644 index 0000000000..bd08c53d64 --- /dev/null +++ b/TESTS/mbed_hal/qspi/qspi_test_utils.h @@ -0,0 +1,117 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_QSPI_TEST_UTILS_H +#define MBED_QSPI_TEST_UTILS_H + +#include "flash_configs/flash_configs.h" +#include "unity/unity.h" + +#define QSPI_NONE (-1) + +struct QspiCommand { + + void configure(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width, + qspi_bus_width_t alt_width, qspi_address_size_t addr_size, qspi_alt_size_t alt_size, + int dummy_cycles = 0); + + void build(int instruction, int address = QSPI_NONE, int alt = QSPI_NONE); + + qspi_command_t * get(); + + qspi_command_t cmd; +}; + +struct Qspi { + qspi_t handle; + QspiCommand cmd; +}; + +// MODE_Command_Address_Data_Alt +#define MODE_1_1_1 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE +#define MODE_1_1_2 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_DUAL +#define MODE_1_2_2 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_DUAL +#define MODE_1_1_4 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_SINGLE +#define MODE_1_4_4 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_QUAD + +#define WRITE_1_1_1 MODE_1_1_1, QSPI_CMD_WRITE_1IO +#ifdef QSPI_CMD_WRITE_4IO +#define WRITE_1_4_4 MODE_1_4_4, QSPI_CMD_WRITE_4IO +#endif + + +#define READ_1_1_1 MODE_1_1_1, QSPI_CMD_READ_1IO, QSPI_READ_1IO_DUMMY_CYCLE +#define READ_1_1_2 MODE_1_1_2, QSPI_CMD_READ_1I2O, QSPI_READ_1I2O_DUMMY_CYCLE +#define READ_1_2_2 MODE_1_2_2, QSPI_CMD_READ_2IO, QSPI_READ_2IO_DUMMY_CYCLE +#define READ_1_1_4 MODE_1_1_4, QSPI_CMD_READ_1I4O, QSPI_READ_1I4O_DUMMY_CYCLE +#define READ_1_4_4 MODE_1_4_4, QSPI_CMD_READ_4IO, QSPI_READ_4IO_DUMMY_CYCLE + + +#define ADDR_SIZE_8 QSPI_CFG_ADDR_SIZE_8 +#define ADDR_SIZE_16 QSPI_CFG_ADDR_SIZE_16 +#define ADDR_SIZE_24 QSPI_CFG_ADDR_SIZE_24 +#define ADDR_SIZE_32 QSPI_CFG_ADDR_SIZE_32 + +#define ALT_SIZE_8 QSPI_CFG_ALT_SIZE_8 +#define ALT_SIZE_16 QSPI_CFG_ALT_SIZE_16 +#define ALT_SIZE_24 QSPI_CFG_ALT_SIZE_24 +#define ALT_SIZE_32 QSPI_CFG_ALT_SIZE_32 + +#define STATUS_REG QSPI_CMD_RDSR +#define CONFIG_REG QSPI_CMD_RDCR +#define SECURITY_REG QSPI_CMD_RDSCUR + + +#define SECTOR_ERASE QSPI_CMD_ERASE_SECTOR +#define BLOCK_ERASE QSPI_CMD_ERASE_BLOCK_64 + + +#define SECTOR_ERASE_MAX_TIME QSPI_ERASE_SECTOR_MAX_TIME +#define BLOCK32_ERASE_MAX_TIME QSPI_ERASE_BLOCK_32_MAX_TIME +#define BLOCK64_ERASE_MAX_TIME QSPI_ERASE_BLOCK_64_MAX_TIME +#define PAGE_PROG_MAX_TIME QSPI_PAGE_PROG_MAX_TIME +#define WRSR_MAX_TIME QSPI_WRSR_MAX_TIME +#define WAIT_MAX_TIME QSPI_WAIT_MAX_TIME + + + +qspi_status_t read_register(uint32_t cmd, uint8_t *buf, uint32_t size, Qspi &q); + +bool flash_wait_for(uint32_t time_us, Qspi &qspi); + +void flash_init(Qspi &qspi); + +qspi_status_t write_enable(Qspi &qspi); + +qspi_status_t write_disable(Qspi &qspi); + +qspi_status_t dual_enable(Qspi &qspi); + +qspi_status_t dual_disable(Qspi &qspi); + +qspi_status_t quad_enable(Qspi &qspi); + +qspi_status_t quad_disable(Qspi &qspi); + +qspi_status_t fast_mode_enable(Qspi &qspi); + +qspi_status_t erase(uint32_t erase_cmd, uint32_t flash_addr, Qspi &qspi); + +#define WAIT_FOR(timeout, q) \ + if(!flash_wait_for(timeout, q)) { \ + TEST_ASSERT_MESSAGE(false, "flash_wait_for failed!!!"); \ + } + +#endif // MBED_QSPI_TEST_UTILS_H