add hal-qspi test

pull/7783/head
Maciej Bocianski 2018-06-26 09:03:25 +02:00
parent 8b36d6b39a
commit 443273785f
8 changed files with 1050 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<PinName>(QSPI_PIN_IO0)
#define QPIN_1 static_cast<PinName>(QSPI_PIN_IO1)
#define QPIN_2 static_cast<PinName>(QSPI_PIN_IO2)
#define QPIN_3 static_cast<PinName>(QSPI_PIN_IO3)
#define QSCK static_cast<PinName>(QSPI_PIN_SCK)
#define QCSN static_cast<PinName>(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<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>),
Case("qspi write(1-1-1)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test<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_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-1)/x1 repeat/x16 test", qspi_write_read_test<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_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-2)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-2-2)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-4)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-4-4)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef QSPI_CMD_WRITE_4IO
Case("qspi write(1-4-4)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, 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>),
Case("qspi write(1-4-4)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, 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_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-1)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_4_4, 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_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-2)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-2-2)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-4)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-4-4)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#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);
}

View File

@ -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
/** @}*/

View File

@ -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 <string.h> // 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);
}

View File

@ -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