add opsi driver

pull/12644/head
rogeryou 2020-09-16 11:27:23 +08:00
parent 0db72d0cf2
commit 48524f25ae
28 changed files with 6018 additions and 16 deletions

View File

@ -0,0 +1,272 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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_OSPI_H
#define MBED_OSPI_H
#include "platform/platform.h"
#if DEVICE_OSPI || defined(DOXYGEN_ONLY)
#include "hal/ospi_api.h"
#include "platform/PlatformMutex.h"
#include "platform/SingletonPtr.h"
#include "platform/NonCopyable.h"
#define ONE_MHZ 1000000
#define OSPI_NO_INST (-1)
namespace mbed {
/** \defgroup drivers-public-api-spi SPI
* \ingroup drivers-public-api
*/
/**
* \defgroup drivers_OSPI OSPI class
* \ingroup drivers-public-api-spi
* @{
*/
/** Type representing a OSPI instruction
*/
typedef int ospi_inst_t;
/** A OSPI Driver, used for communicating with OSPI slave devices
*
* The default format is set to OCTO-SPI(1-1-1), and a clock frequency of 1MHz
* Most OSPI devices will also require Chip Select which is indicated by ssel.
*
* @note Synchronization level: Thread safe
*
* Example:
* @code
* // Write 4 byte array to a OSPI slave, and read the response, note that each device will have its specific read/write/alt values defined
*
* #include "mbed.h"
*
* #define CMD_WRITE 0x02
* #define CMD_READ 0x03
* #define ADDRESS 0x1000
*
* // hardware ssel (where applicable)
* OSPI ospi_device(OSPI_FLASH1_IO0, OSPI_FLASH1_IO1, OSPI_FLASH1_IO2, OSPI_FLASH1_IO3, OSPI_FLASH1_IO4, OSPI_FLASH1_IO5, OSPI_FLASH1_IO6,
* OSPI_FLASH1_SCK, OSPI_FLASH1_CSN, OSPI_FLASH1_DQS); // io0, io1, io2, io3, io4, io5, io6, io7, sclk, ssel, dqs
*
*
* int main() {
* char tx_buf[] = { 0x11, 0x22, 0x33, 0x44 };
* char rx_buf[4];
* int buf_len = sizeof(tx_buf);
*
* ospi_status_t result = ospi_device.write(CMD_WRITE, 0, ADDRESS, tx_buf, &buf_len);
* if (result != OSPI_STATUS_OK) {
* printf("Write failed");
* }
* result = ospi_device.read(CMD_READ, 0, ADDRESS, rx_buf, &buf_len);
* if (result != OSPI_STATUS_OK) {
* printf("Read failed");
* }
*
* }
* @endcode
*/
class OSPI : private NonCopyable<OSPI> {
public:
/** Create a OSPI master connected to the specified pins
*
* io0-io3 is used to specify the Pins used for Quad SPI mode
*
* @param io0 1st IO pin used for sending/receiving data during data phase of a transaction
* @param io1 2nd IO pin used for sending/receiving data during data phase of a transaction
* @param io2 3rd IO pin used for sending/receiving data during data phase of a transaction
* @param io3 4th IO pin used for sending/receiving data during data phase of a transaction
* @param io4 5th IO pin used for sending/receiving data during data phase of a transaction
* @param io5 6th IO pin used for sending/receiving data during data phase of a transaction
* @param io6 7th IO pin used for sending/receiving data during data phase of a transaction
* @param io7 8th IO pin used for sending/receiving data during data phase of a transaction
* @param sclk OSPI Clock pin
* @param ssel OSPI chip select pin
* @param dqs OSPI dqs pin
* @param mode Clock polarity and phase mode (0 - 3) of SPI
* (Default: Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
*
*/
OSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName io4, PinName io5, PinName io6, PinName io7,
PinName sclk, PinName ssel = NC, PinName dqs = NC, int mode = 0);
/** Create a OSPI master connected to the specified pins
*
* io0-io3 is used to specify the Pins used for Quad SPI mode
*
* @param pinmap reference to structure which holds static pinmap
* @param mode Clock polarity and phase mode (0 - 3) of SPI
* (Default: Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
*
*/
OSPI(const ospi_pinmap_t &pinmap, int mode = 0);
OSPI(const ospi_pinmap_t &&, int = 0) = delete; // prevent passing of temporary objects
virtual ~OSPI()
{
}
/** Configure the data transmission format
*
* @param inst_width Bus width used by instruction phase(Valid values are OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_QUAD)
* @param inst_size Size in bits used by instruction phase
* @param address_width Bus width used by address phase(Valid values are OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_QUAD)
* @param address_size Size in bits used by address phase(Valid values are OSPI_CFG_ADDR_SIZE_8, OSPI_CFG_ADDR_SIZE_16, OSPI_CFG_ADDR_SIZE_24, OSPI_CFG_ADDR_SIZE_32)
* @param alt_width Bus width used by alt phase(Valid values are OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_QUAD)
* @param alt_size Size in bits used by alt phase (must be a multiple of the number of bus lines indicated in alt_width)
* @param data_width Bus width used by data phase(Valid values are OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_QUAD)
* @param dummy_cycles Number of dummy clock cycles to be used after alt phase
*
*/
ospi_status_t configure_format(ospi_bus_width_t inst_width,
ospi_inst_size_t inst_size,
ospi_bus_width_t address_width,
ospi_address_size_t address_size,
ospi_bus_width_t alt_width,
ospi_alt_size_t alt_size,
ospi_bus_width_t data_width,
int dummy_cycles);
/** Set the ospi bus clock frequency
*
* @param hz SCLK frequency in hz (default = 1MHz)
* @returns
* Returns OSPI_STATUS_SUCCESS on successful, fails if the interface is already init-ed
*/
ospi_status_t set_frequency(int hz = ONE_MHZ);
/** Read from OSPI peripheral with the preset read_instruction and alt_value
*
* @param address Address to be accessed in OSPI peripheral
* @param rx_buffer Buffer for data to be read from the peripheral
* @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
*
* @returns
* Returns OSPI_STATUS_SUCCESS on successful reads and OSPI_STATUS_ERROR on failed reads.
*/
ospi_status_t read(int address, char *rx_buffer, size_t *rx_length);
/** Write to OSPI peripheral using custom write instruction
*
* @param address Address to be accessed in OSPI peripheral
* @param tx_buffer Buffer containing data to be sent to peripheral
* @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
*
* @returns
* Returns OSPI_STATUS_SUCCESS on successful reads and OSPI_STATUS_ERROR on failed reads.
*/
ospi_status_t write(int address, const char *tx_buffer, size_t *tx_length);
/** Read from OSPI peripheral using custom read instruction, alt values
*
* @param instruction Instruction value to be used in instruction phase. Use OSPI_NO_INST to skip the instruction phase
* @param alt Alt value to be used in Alternate-byte phase. Use -1 for ignoring Alternate-byte phase
* @param address Address to be accessed in OSPI peripheral
* @param rx_buffer Buffer for data to be read from the peripheral
* @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
*
* @returns
* Returns OSPI_STATUS_SUCCESS on successful reads and OSPI_STATUS_ERROR on failed reads.
*/
ospi_status_t read(ospi_inst_t instruction, int alt, int address, char *rx_buffer, size_t *rx_length);
/** Write to OSPI peripheral using custom write instruction, alt values
*
* @param instruction Instruction value to be used in instruction phase. Use OSPI_NO_INST to skip the instruction phase
* @param alt Alt value to be used in Alternate-byte phase. Use -1 for ignoring Alternate-byte phase
* @param address Address to be accessed in OSPI peripheral
* @param tx_buffer Buffer containing data to be sent to peripheral
* @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
*
* @returns
* Returns OSPI_STATUS_SUCCESS on successful reads and OSPI_STATUS_ERROR on failed reads.
*/
ospi_status_t write(ospi_inst_t instruction, int alt, int address, const char *tx_buffer, size_t *tx_length);
/** Perform a transaction to write to an address(a control register) and get the status results
*
* @param instruction Instruction value to be used in instruction phase. Use OSPI_NO_INST to skip the instruction phase
* @param address Some instruction might require address. Use -1 if no address
* @param tx_buffer Buffer containing data to be sent to peripheral
* @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written
* @param rx_buffer Buffer for data to be read from the peripheral
* @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read
*
* @returns
* Returns OSPI_STATUS_SUCCESS on successful reads and OSPI_STATUS_ERROR on failed reads.
*/
ospi_status_t command_transfer(ospi_inst_t instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length);
#if !defined(DOXYGEN_ONLY)
protected:
/** Acquire exclusive access to this SPI bus
*/
virtual void lock(void);
/** Release exclusive access to this SPI bus
*/
virtual void unlock(void);
ospi_t _ospi;
bool acquire(void);
static OSPI *_owner;
static SingletonPtr<PlatformMutex> _mutex;
ospi_bus_width_t _inst_width; //Bus width for Instruction phase
ospi_inst_size_t _inst_size; //Instruction Size
ospi_bus_width_t _address_width; //Bus width for Address phase
ospi_address_size_t _address_size;
ospi_bus_width_t _alt_width; //Bus width for Alt phase
ospi_alt_size_t _alt_size;
ospi_bus_width_t _data_width; //Bus width for Data phase
ospi_command_t _ospi_command; //OSPI Hal command struct
unsigned int _num_dummy_cycles; //Number of dummy cycles to be used
int _hz; //Bus Frequency
int _mode; //SPI mode
bool _initialized;
PinName _ospi_io0, _ospi_io1, _ospi_io2, _ospi_io3, _ospi_io4, _ospi_io5, _ospi_io6, _ospi_io7, _ospi_clk, _ospi_cs, _ospi_dqs; //IO lines, clock, chip select and dqs
const ospi_pinmap_t *_static_pinmap;
bool (OSPI::* _init_func)(void);
private:
/* Private acquire function without locking/unlocking
* Implemented in order to avoid duplicate locking and boost performance
*/
bool _acquire(void);
bool _initialize();
bool _initialize_direct();
/*
* This function builds the ospi command struct to be send to Hal
*/
inline void _build_ospi_command(ospi_inst_t instruction, int address, int alt);
#endif
};
/** @}*/
} // namespace mbed
#endif
#endif

View File

@ -68,10 +68,18 @@ struct sfdp_smptbl_info {
unsigned int erase_type_size_arr[SFDP_MAX_NUM_OF_ERASE_TYPES]; ///< Erase sizes for all different erase types
};
/** JEDEC 4-byte Address Instruction Parameter Table info */
struct sfdp_fbatbl_info {
uint32_t addr; ///< Address
size_t size; ///< Size
int erase_type_4_byte_inst_arr[SFDP_MAX_NUM_OF_ERASE_TYPES]; ///< // Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size)
};
/** SFDP JEDEC Parameter Table info */
struct sfdp_hdr_info {
sfdp_bptbl_info bptbl;
sfdp_smptbl_info smptbl;
sfdp_fbatbl_info fbatbl;
};
/** Parse SFDP Database

View File

@ -41,6 +41,50 @@
"qspi_csn": {
"help": "QSPI chip select pin",
"value": "QSPI_FLASH1_CSN"
},
"ospi_io0": {
"help": "OSPI data I/O 0 pin",
"value": "OSPI_FLASH1_IO0"
},
"ospi_io1": {
"help": "OSPI data I/O 1 pin",
"value": "OSPI_FLASH1_IO1"
},
"ospi_io2": {
"help": "OSPI data I/O 2 pin",
"value": "OSPI_FLASH1_IO2"
},
"ospi_io3": {
"help": "OSPI data I/O 3 pin",
"value": "OSPI_FLASH1_IO3"
},
"ospi_io4": {
"help": "OSPI data I/O 4 pin",
"value": "OSPI_FLASH1_IO4"
},
"ospi_io5": {
"help": "OSPI data I/O 5 pin",
"value": "OSPI_FLASH1_IO5"
},
"ospi_io6": {
"help": "OSPI data I/O 6 pin",
"value": "OSPI_FLASH1_IO6"
},
"ospi_io7": {
"help": "OSPI data I/O 7 pin",
"value": "OSPI_FLASH1_IO7"
},
"ospi_sck": {
"help": "OSPI clock pin",
"value": "OSPI_FLASH1_SCK"
},
"ospi_csn": {
"help": "OSPI chip select pin",
"value": "OSPI_FLASH1_CSN"
},
"ospi_dqs": {
"help": "OSPI dqs pin",
"value": "OSPI_FLASH1_DQS"
}
}
}

378
drivers/source/OSPI.cpp Normal file
View File

@ -0,0 +1,378 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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 "drivers/OSPI.h"
#include "platform/mbed_critical.h"
#include <string.h>
#if DEVICE_OSPI
namespace mbed {
OSPI *OSPI::_owner = NULL;
SingletonPtr<PlatformMutex> OSPI::_mutex;
uint8_t convert_bus_width_to_line_count(ospi_bus_width_t width)
{
switch (width) {
case OSPI_CFG_BUS_SINGLE:
return 1;
case OSPI_CFG_BUS_DUAL:
return 2;
case OSPI_CFG_BUS_QUAD:
return 4;
case OSPI_CFG_BUS_OCTA:
case OSPI_CFG_BUS_OCTA_DTR:
return 8;
default:
// Unrecognized bus width
return 0;
}
}
OSPI::OSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName io4, PinName io5, PinName io6, PinName io7,
PinName sclk, PinName ssel, PinName dqs, int mode) : _ospi()
{
_ospi_io0 = io0;
_ospi_io1 = io1;
_ospi_io2 = io2;
_ospi_io3 = io3;
_ospi_io4 = io4;
_ospi_io5 = io5;
_ospi_io6 = io6;
_ospi_io7 = io7;
_ospi_clk = sclk;
_ospi_cs = ssel;
_ospi_dqs = dqs;
_static_pinmap = NULL;
_inst_width = OSPI_CFG_BUS_SINGLE;
_inst_size = OSPI_CFG_INST_SIZE_8;
_address_width = OSPI_CFG_BUS_SINGLE;
_address_size = OSPI_CFG_ADDR_SIZE_24;
_alt_width = OSPI_CFG_BUS_SINGLE;
_alt_size = 0;
_data_width = OSPI_CFG_BUS_SINGLE;
_num_dummy_cycles = 0;
_mode = mode;
_hz = ONE_MHZ;
_initialized = false;
_init_func = &OSPI::_initialize;
//Go ahead init the device here with the default config
bool success = (this->*_init_func)();
MBED_ASSERT(success);
}
OSPI::OSPI(const ospi_pinmap_t &pinmap, int mode) : _ospi()
{
_ospi_io0 = pinmap.data0_pin;
_ospi_io1 = pinmap.data1_pin;
_ospi_io2 = pinmap.data2_pin;
_ospi_io3 = pinmap.data3_pin;
_ospi_io4 = pinmap.data4_pin;
_ospi_io5 = pinmap.data5_pin;
_ospi_io6 = pinmap.data6_pin;
_ospi_io7 = pinmap.data7_pin;
_ospi_clk = pinmap.sclk_pin;
_ospi_cs = pinmap.ssel_pin;
_ospi_dqs = pinmap.dqs_pin;
_static_pinmap = &pinmap;
_inst_width = OSPI_CFG_BUS_SINGLE;
_inst_size = OSPI_CFG_INST_SIZE_8;
_address_width = OSPI_CFG_BUS_SINGLE;
_address_size = OSPI_CFG_ADDR_SIZE_24;
_alt_width = OSPI_CFG_BUS_SINGLE;
_alt_size = OSPI_CFG_ALT_SIZE_8;
_data_width = OSPI_CFG_BUS_SINGLE;
_num_dummy_cycles = 0;
_mode = mode;
_hz = ONE_MHZ;
_initialized = false;
_init_func = &OSPI::_initialize_direct;
//Go ahead init the device here with the default config
bool success = (this->*_init_func)();
MBED_ASSERT(success);
}
ospi_status_t OSPI::configure_format(ospi_bus_width_t inst_width, ospi_inst_size_t inst_size,
ospi_bus_width_t address_width, ospi_address_size_t address_size,
ospi_bus_width_t alt_width, ospi_alt_size_t alt_size,
ospi_bus_width_t data_width, int dummy_cycles)
{
// Check that alt_size/alt_width are a valid combination
uint8_t alt_lines = convert_bus_width_to_line_count(alt_width);
if (alt_lines == 0) {
return OSPI_STATUS_ERROR;
} else if (alt_size % alt_lines != 0) {
// Invalid alt size/width combination (alt size is not a multiple of the number of bus lines used to transmit it)
return OSPI_STATUS_ERROR;
}
lock();
_inst_width = inst_width;
_inst_size = inst_size;
_address_width = address_width;
_address_size = address_size;
_alt_width = alt_width;
_alt_size = alt_size;
_data_width = data_width;
_num_dummy_cycles = dummy_cycles;
unlock();
return OSPI_STATUS_OK;
}
ospi_status_t OSPI::set_frequency(int hz)
{
ospi_status_t ret_status = OSPI_STATUS_OK;
if (_initialized) {
lock();
_hz = hz;
//If the same owner, just change freq.
//Otherwise we may have to change mode as well, so call _acquire
if (_owner == this) {
if (OSPI_STATUS_OK != ospi_frequency(&_ospi, _hz)) {
ret_status = OSPI_STATUS_ERROR;
}
} else {
_acquire();
}
unlock();
} else {
ret_status = OSPI_STATUS_ERROR;
}
return ret_status;
}
ospi_status_t OSPI::read(int address, char *rx_buffer, size_t *rx_length)
{
ospi_status_t ret_status = OSPI_STATUS_ERROR;
if (_initialized) {
if ((rx_length != NULL) && (rx_buffer != NULL)) {
if (*rx_length != 0) {
lock();
if (true == _acquire()) {
_build_ospi_command(OSPI_NO_INST, address, -1);
if (OSPI_STATUS_OK == ospi_read(&_ospi, &_ospi_command, rx_buffer, rx_length)) {
ret_status = OSPI_STATUS_OK;
}
}
unlock();
}
} else {
ret_status = OSPI_STATUS_INVALID_PARAMETER;
}
}
return ret_status;
}
ospi_status_t OSPI::write(int address, const char *tx_buffer, size_t *tx_length)
{
ospi_status_t ret_status = OSPI_STATUS_ERROR;
if (_initialized) {
if ((tx_length != NULL) && (tx_buffer != NULL)) {
if (*tx_length != 0) {
lock();
if (true == _acquire()) {
_build_ospi_command(OSPI_NO_INST, address, -1);
if (OSPI_STATUS_OK == ospi_write(&_ospi, &_ospi_command, tx_buffer, tx_length)) {
ret_status = OSPI_STATUS_OK;
}
}
unlock();
}
} else {
ret_status = OSPI_STATUS_INVALID_PARAMETER;
}
}
return ret_status;
}
ospi_status_t OSPI::read(ospi_inst_t instruction, int alt, int address, char *rx_buffer, size_t *rx_length)
{
ospi_status_t ret_status = OSPI_STATUS_ERROR;
if (_initialized) {
if ((rx_length != NULL) && (rx_buffer != NULL)) {
if (*rx_length != 0) {
lock();
if (true == _acquire()) {
_build_ospi_command(instruction, address, alt);
if (OSPI_STATUS_OK == ospi_read(&_ospi, &_ospi_command, rx_buffer, rx_length)) {
ret_status = OSPI_STATUS_OK;
}
}
unlock();
}
} else {
ret_status = OSPI_STATUS_INVALID_PARAMETER;
}
}
return ret_status;
}
ospi_status_t OSPI::write(ospi_inst_t instruction, int alt, int address, const char *tx_buffer, size_t *tx_length)
{
ospi_status_t ret_status = OSPI_STATUS_ERROR;
if (_initialized) {
if ((tx_length != NULL) && (tx_buffer != NULL)) {
if (*tx_length != 0) {
lock();
if (true == _acquire()) {
_build_ospi_command(instruction, address, alt);
if (OSPI_STATUS_OK == ospi_write(&_ospi, &_ospi_command, tx_buffer, tx_length)) {
ret_status = OSPI_STATUS_OK;
}
}
unlock();
}
} else {
ret_status = OSPI_STATUS_INVALID_PARAMETER;
}
}
return ret_status;
}
ospi_status_t OSPI::command_transfer(ospi_inst_t instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length)
{
ospi_status_t ret_status = OSPI_STATUS_ERROR;
if (_initialized) {
lock();
if (true == _acquire()) {
_build_ospi_command(instruction, address, -1); //We just need the command
if (OSPI_STATUS_OK == ospi_command_transfer(&_ospi, &_ospi_command, (const void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length)) {
ret_status = OSPI_STATUS_OK;
}
}
unlock();
}
return ret_status;
}
void OSPI::lock()
{
_mutex->lock();
}
void OSPI::unlock()
{
_mutex->unlock();
}
// Note: Private helper function to initialize ospi HAL
bool OSPI::_initialize()
{
if (_mode != 0 && _mode != 1) {
_initialized = false;
return _initialized;
}
ospi_status_t ret = ospi_init(&_ospi, _ospi_io0, _ospi_io1, _ospi_io2, _ospi_io3, _ospi_io4, _ospi_io5, _ospi_io6, _ospi_io7, _ospi_clk, _ospi_cs, _ospi_dqs, _hz, _mode);
if (OSPI_STATUS_OK == ret) {
_initialized = true;
_owner = this;
} else {
_initialized = false;
}
return _initialized;
}
// Note: Private helper function to initialize ospi HAL
bool OSPI::_initialize_direct()
{
if (_mode != 0 && _mode != 1) {
_initialized = false;
return _initialized;
}
ospi_status_t ret = ospi_init_direct(&_ospi, _static_pinmap, _hz, _mode);
if (OSPI_STATUS_OK == ret) {
_initialized = true;
_owner = this;
} else {
_initialized = false;
}
return _initialized;
}
// Note: Private function with no locking
bool OSPI::_acquire()
{
if (_owner != this) {
//This will set freq as well
(this->*_init_func)();
_owner = this;
}
return _initialized;
}
void OSPI::_build_ospi_command(ospi_inst_t instruction, int address, int alt)
{
memset(&_ospi_command, 0, sizeof(ospi_command_t));
//Set up instruction phase parameters
_ospi_command.instruction.bus_width = _inst_width;
if (instruction != OSPI_NO_INST) {
_ospi_command.instruction.value = instruction;
_ospi_command.instruction.disabled = false;
} else {
_ospi_command.instruction.disabled = true;
}
//Set up address phase parameters
_ospi_command.address.bus_width = _address_width;
_ospi_command.address.size = _address_size;
if (address != -1) {
_ospi_command.address.value = address;
_ospi_command.address.disabled = false;
} else {
_ospi_command.address.disabled = true;
}
//Set up alt phase parameters
_ospi_command.alt.bus_width = _alt_width;
_ospi_command.alt.size = _alt_size;
if (alt != -1) {
_ospi_command.alt.value = alt;
_ospi_command.alt.disabled = false;
} else {
_ospi_command.alt.disabled = true;
}
_ospi_command.dummy_count = _num_dummy_cycles;
//Set up bus width for data phase
_ospi_command.data.bus_width = _data_width;
}
} // namespace mbed
#endif

View File

@ -24,7 +24,7 @@
#include "platform/mbed_error.h"
#include "drivers/internal/SFDP.h"
#if (DEVICE_SPI || DEVICE_QSPI)
#if (DEVICE_SPI || DEVICE_QSPI || DEVICE_OSPI)
#if MBED_CONF_MBED_TRACE_ENABLE
#include "mbed-trace/mbed_trace.h"
@ -136,13 +136,15 @@ int sfdp_parse_single_param_header(sfdp_prm_hdr *phdr_ptr, sfdp_hdr_info &hdr_in
hdr_info.smptbl.addr = sfdp_get_param_tbl_ptr(phdr_ptr->DWORD2);
hdr_info.smptbl.size = phdr_ptr->P_LEN * 4;
break;
case 0x84:
tr_info("Parameter header: 4-byte Address Instruction");
hdr_info.fbatbl.addr = sfdp_get_param_tbl_ptr(phdr_ptr->DWORD2);
hdr_info.fbatbl.size = phdr_ptr->P_LEN * 4;
break;
/* Unsupported */
case 0x03:
tr_info("UNSUPPORTED:Parameter header: Replay Protected Monotonic Counters");
break;
case 0x84:
tr_info("UNSUPPORTED:Parameter header: 4-byte Address Instruction");
break;
case 0x05:
tr_info("UNSUPPORTED:Parameter header: eXtended Serial Peripheral Interface (xSPI) Profile 1.0");
break;
@ -443,7 +445,7 @@ int sfdp_detect_device_density(uint8_t *bptbl_ptr, sfdp_bptbl_info &bptbl_info)
return 0;
}
#if DEVICE_QSPI
#if (DEVICE_QSPI || DEVICE_OSPI)
int sfdp_detect_addressability(uint8_t *bptbl_ptr, sfdp_bptbl_info &bptbl_info)
{
// Check that density is not greater than 4 gigabits (i.e. that addressing beyond 4 bytes is not required)
@ -466,4 +468,4 @@ int sfdp_detect_addressability(uint8_t *bptbl_ptr, sfdp_bptbl_info &bptbl_info)
#endif
} /* namespace mbed */
#endif /* (DEVICE_SPI || DEVICE_QSPI) */
#endif /* (DEVICE_SPI || DEVICE_QSPI || DEVICE_OSPI) */

354
hal/include/hal/ospi_api.h Normal file
View File

@ -0,0 +1,354 @@
/** \addtogroup hal */
/** @{*/
/* mbed Microcontroller Library
* Copyright (c) 2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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_OSPI_API_H
#define MBED_OSPI_API_H
#include "device.h"
#include "pinmap.h"
#include <stdbool.h>
#if DEVICE_OSPI
#ifdef __cplusplus
extern "C" {
#endif
/**
* \defgroup hal_ospi OSPI HAL
* @{
*/
/** OSPI HAL object
*/
typedef struct ospi_s ospi_t;
typedef struct {
int peripheral;
PinName data0_pin;
int data0_function;
PinName data1_pin;
int data1_function;
PinName data2_pin;
int data2_function;
PinName data3_pin;
int data3_function;
PinName data4_pin;
int data4_function;
PinName data5_pin;
int data5_function;
PinName data6_pin;
int data6_function;
PinName data7_pin;
int data7_function;
PinName sclk_pin;
int sclk_function;
PinName ssel_pin;
int ssel_function;
PinName dqs_pin;
int dqs_function;
} ospi_pinmap_t;
/** OSPI Bus width
*
* Some parts of commands provide variable bus width
*/
typedef enum ospi_bus_width {
OSPI_CFG_BUS_SINGLE,
OSPI_CFG_BUS_DUAL,
OSPI_CFG_BUS_QUAD,
OSPI_CFG_BUS_OCTA,
OSPI_CFG_BUS_OCTA_DTR,
} ospi_bus_width_t;
/** Instruction size in bits
*/
typedef enum ospi_inst_size {
OSPI_CFG_INST_SIZE_8, /* 1 byte for SPI mode */
OSPI_CFG_INST_SIZE_16, /* 2 byte for OPI mode */
} ospi_inst_size_t;
/** Address size in bits
*/
typedef enum ospi_address_size {
OSPI_CFG_ADDR_SIZE_8,
OSPI_CFG_ADDR_SIZE_16,
OSPI_CFG_ADDR_SIZE_24,
OSPI_CFG_ADDR_SIZE_32,
} ospi_address_size_t;
/** Alternative size in bits
*/
typedef uint8_t ospi_alt_size_t;
// The following defines are provided for backwards compatibilty. New code should explicitly
// specify the required number of alt bits.
#define OSPI_CFG_ALT_SIZE_8 8u
#define OSPI_CFG_ALT_SIZE_16 16u
#define OSPI_CFG_ALT_SIZE_24 24u
#define OSPI_CFG_ALT_SIZE_32 32u
/** OSPI command
*
* Defines a frame format. It consists of instruction, address, alternative, dummy count and data
*/
typedef struct ospi_command {
struct {
ospi_bus_width_t bus_width; /**< Bus width for the instruction >*/
ospi_inst_size_t size; /**< Inst size >*/
uint32_t value; /**< Instruction value >*/
bool disabled; /**< Instruction phase skipped if disabled is set to true >*/
} instruction;
struct {
ospi_bus_width_t bus_width; /**< Bus width for the address >*/
ospi_address_size_t size; /**< Address size >*/
uint32_t value; /**< Address value >*/
bool disabled; /**< Address phase skipped if disabled is set to true >*/
} address;
struct {
ospi_bus_width_t bus_width; /**< Bus width for alternative >*/
ospi_alt_size_t size; /**< Alternative size >*/
uint32_t value; /**< Alternative value >*/
bool disabled; /**< Alternative phase skipped if disabled is set to true >*/
} alt;
uint8_t dummy_count; /**< Dummy cycles count >*/
struct {
ospi_bus_width_t bus_width; /**< Bus width for data >*/
} data;
} ospi_command_t;
/** OSPI return status
*/
typedef enum ospi_status {
OSPI_STATUS_ERROR = -1, /**< Generic error >*/
OSPI_STATUS_INVALID_PARAMETER = -2, /**< The parameter is invalid >*/
OSPI_STATUS_OK = 0, /**< Function executed sucessfully >*/
} ospi_status_t;
/** Initialize OSPI peripheral.
*
* It should initialize OSPI pins (io0-io7, sclk, ssel and dqs), set frequency, clock polarity and phase mode. The clock for the peripheral should be enabled
*
* @param obj OSPI object
* @param io0 Data pin 0
* @param io1 Data pin 1
* @param io2 Data pin 2
* @param io3 Data pin 3
* @param io4 Data pin 4
* @param io5 Data pin 5
* @param io6 Data pin 6
* @param io7 Data pin 7
* @param sclk The clock pin
* @param ssel The chip select pin
* @param dqs The chip dqs pin
* @param hz The bus frequency
* @param mode Clock polarity and phase mode (0 - 3)
* @return OSPI_STATUS_OK if initialisation successfully executed
OSPI_STATUS_INVALID_PARAMETER if invalid parameter found
OSPI_STATUS_ERROR otherwise
*/
ospi_status_t ospi_init(ospi_t *obj, PinName io0, PinName io1, PinName io2, PinName io3, PinName io4, PinName io5, PinName io6, PinName io7,
PinName sclk, PinName ssel, PinName dqs, uint32_t hz, uint8_t mode);
/** Initialize OSPI peripheral.
*
* It should initialize OSPI pins (io0-io7, sclk, ssel and dqs), set frequency, clock polarity and phase mode. The clock for the peripheral should be enabled
*
* @param obj OSPI object
* @param pinmap pointer to structure which holds static pinmap
* @param hz The bus frequency
* @param mode Clock polarity and phase mode (0 - 3)
* @return OSPI_STATUS_OK if initialisation successfully executed
OSPI_STATUS_INVALID_PARAMETER if invalid parameter found
OSPI_STATUS_ERROR otherwise
*/
ospi_status_t ospi_init_direct(ospi_t *obj, const ospi_pinmap_t *pinmap, uint32_t hz, uint8_t mode);
/** Deinitialize OSPI peripheral
*
* It should release pins that are associated with the OSPI object, and disable clocks for OSPI peripheral module that was associated with the object
*
* @param obj OSPI object
* @return OSPI_STATUS_OK if deinitialisation successfully executed
OSPI_STATUS_INVALID_PARAMETER if invalid parameter found
OSPI_STATUS_ERROR otherwise
*/
ospi_status_t ospi_free(ospi_t *obj);
/** Set the OSPI baud rate
*
* Actual frequency may differ from the desired frequency due to available dividers and the bus clock
* Configures the OSPI peripheral's baud rate
* @param obj The SPI object to configure
* @param hz The baud rate in Hz
* @return OSPI_STATUS_OK if frequency was set
OSPI_STATUS_INVALID_PARAMETER if invalid parameter found
OSPI_STATUS_ERROR otherwise
*/
ospi_status_t ospi_frequency(ospi_t *obj, int hz);
/** Send a command and block of data
*
* @param obj OSPI object
* @param command OSPI command
* @param data TX buffer
* @param[in,out] length in - TX buffer length in bytes, out - number of bytes written
* @return OSPI_STATUS_OK if the data has been succesfully sent
OSPI_STATUS_INVALID_PARAMETER if invalid parameter found
OSPI_STATUS_ERROR otherwise
*/
ospi_status_t ospi_write(ospi_t *obj, const ospi_command_t *command, const void *data, size_t *length);
/** Send a command (and optionally data) and get the response. Can be used to send/receive device specific commands
*
* @param obj OSPI object
* @param command OSPI command
* @param tx_data TX buffer
* @param tx_size TX buffer length in bytes
* @param rx_data RX buffer
* @param rx_size RX buffer length in bytes
* @return OSPI_STATUS_OK if the data has been succesfully sent
OSPI_STATUS_INVALID_PARAMETER if invalid parameter found
OSPI_STATUS_ERROR otherwise
*/
ospi_status_t ospi_command_transfer(ospi_t *obj, const ospi_command_t *command, const void *tx_data, size_t tx_size, void *rx_data, size_t rx_size);
/** Receive a command and block of data
*
* @param obj OSPI object
* @param command OSPI command
* @param data RX buffer
* @param[in,out] length in - RX buffer length in bytes, out - number of bytes read
* @return OSPI_STATUS_OK if data has been succesfully received
OSPI_STATUS_INVALID_PARAMETER if invalid parameter found
OSPI_STATUS_ERROR otherwise
*/
ospi_status_t ospi_read(ospi_t *obj, const ospi_command_t *command, void *data, size_t *length);
/** Get the pins that support OSPI SCLK
*
* Return a PinMap array of pins that support OSPI SCLK in
* master mode. The array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *ospi_master_sclk_pinmap(void);
/** Get the pins that support OSPI SSEL
*
* Return a PinMap array of pins that support OSPI SSEL in
* master mode. The array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *ospi_master_ssel_pinmap(void);
/** Get the pins that support OSPI DQS
*
* Return a PinMap array of pins that support OSPI DQS in
* master mode. The array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *ospi_master_dqs_pinmap(void);
/** Get the pins that support OSPI DATA0
*
* Return a PinMap array of pins that support OSPI DATA0 in
* master mode. The array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *ospi_master_data0_pinmap(void);
/** Get the pins that support OSPI DATA1
*
* Return a PinMap array of pins that support OSPI DATA1 in
* master mode. The array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *ospi_master_data1_pinmap(void);
/** Get the pins that support OSPI DATA2
*
* Return a PinMap array of pins that support OSPI DATA2 in
* master mode. The array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *ospi_master_data2_pinmap(void);
/** Get the pins that support OSPI DATA3
*
* Return a PinMap array of pins that support OSPI DATA3 in
* master mode. The array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *ospi_master_data3_pinmap(void);
/** Get the pins that support OSPI DATA4
*
* Return a PinMap array of pins that support OSPI DATA4 in
* master mode. The array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *ospi_master_data4_pinmap(void);
/** Get the pins that support OSPI DATA5
*
* Return a PinMap array of pins that support OSPI DATA5 in
* master mode. The array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *ospi_master_data5_pinmap(void);
/** Get the pins that support OSPI DATA6
*
* Return a PinMap array of pins that support OSPI DATA6 in
* master mode. The array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *ospi_master_data6_pinmap(void);
/** Get the pins that support OSPI DATA7
*
* Return a PinMap array of pins that support OSPI DATA7 in
* master mode. The array is terminated with {NC, NC, 0}.
*
* @return PinMap array
*/
const PinMap *ospi_master_data7_pinmap(void);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif
#endif
/** @}*/

View File

@ -25,6 +25,7 @@
#include "i2c_api.h"
#include "serial_api.h"
#include "qspi_api.h"
#include "ospi_api.h"
#include "can_api.h"
#include <mstd_cstddef>
@ -293,6 +294,106 @@ MSTD_CONSTEXPR_FN_14 qspi_pinmap_t get_qspi_pinmap(const PinName data0, const Pi
}
#endif //DEVICE_QSPI
#if defined(DEVICE_OSPI) && defined(PINMAP_OSPI_DATA0) && defined(PINMAP_OSPI_DATA1) && defined(PINMAP_OSPI_DATA2) && defined(PINMAP_OSPI_DATA3) && defined(PINMAP_OSPI_DATA4) && defined(PINMAP_OSPI_DATA5) && defined(PINMAP_OSPI_DATA6) && defined(PINMAP_OSPI_DATA7) && defined(PINMAP_OSPI_SCLK) && defined(PINMAP_OSPI_SSEL) && defined(PINMAP_OSPI_DQS)
MSTD_CONSTEXPR_FN_14 ospi_pinmap_t get_ospi_pinmap(const PinName data0, const PinName data1, const PinName data2, const PinName data3, const PinName data4, const PinName data5, const PinName data6, const PinName data7, const PinName sclk, const PinName ssel, const PinName dqs)
{
const PinMap *data0_map = nullptr;
for (const PinMap &pinmap : PINMAP_OSPI_DATA0) {
if (pinmap.pin == data0) {
data0_map = &pinmap;
break;
}
}
const PinMap *data1_map = nullptr;
for (const PinMap &pinmap : PINMAP_OSPI_DATA1) {
if (pinmap.pin == data1) {
data1_map = &pinmap;
break;
}
}
const PinMap *data2_map = nullptr;
for (const PinMap &pinmap : PINMAP_OSPI_DATA2) {
if (pinmap.pin == data2) {
data2_map = &pinmap;
break;
}
}
const PinMap *data3_map = nullptr;
for (const PinMap &pinmap : PINMAP_OSPI_DATA3) {
if (pinmap.pin == data3) {
data3_map = &pinmap;
break;
}
}
const PinMap *data4_map = nullptr;
for (const PinMap &pinmap : PINMAP_OSPI_DATA4) {
if (pinmap.pin == data4) {
data4_map = &pinmap;
break;
}
}
const PinMap *data5_map = nullptr;
for (const PinMap &pinmap : PINMAP_OSPI_DATA5) {
if (pinmap.pin == data5) {
data5_map = &pinmap;
break;
}
}
const PinMap *data6_map = nullptr;
for (const PinMap &pinmap : PINMAP_OSPI_DATA6) {
if (pinmap.pin == data6) {
data6_map = &pinmap;
break;
}
}
const PinMap *data7_map = nullptr;
for (const PinMap &pinmap : PINMAP_OSPI_DATA7) {
if (pinmap.pin == data7) {
data7_map = &pinmap;
break;
}
}
const PinMap *sclk_map = nullptr;
for (const PinMap &pinmap : PINMAP_OSPI_SCLK) {
if (pinmap.pin == sclk) {
sclk_map = &pinmap;
break;
}
}
const PinMap *ssel_map = nullptr;
for (const PinMap &pinmap : PINMAP_OSPI_SSEL) {
if (pinmap.pin == ssel) {
ssel_map = &pinmap;
break;
}
}
const PinMap *dqs_map = nullptr;
for (const PinMap &pinmap : PINMAP_OSPI_DQS) {
if (pinmap.pin == dqs) {
dqs_map = &pinmap;
break;
}
}
if (!data0_map || !data1_map || !data2_map || !data3_map || !data4_map || !data5_map || !data6_map || !data7_map || !sclk_map || !ssel_map || !dqs_map || data0_map->peripheral != data1_map->peripheral || data0_map->peripheral != data2_map->peripheral || data0_map->peripheral != data3_map->peripheral || data0_map->peripheral != data4_map->peripheral || data0_map->peripheral != data5_map->peripheral || data0_map->peripheral != data6_map->peripheral || data0_map->peripheral != data7_map->peripheral || data0_map->peripheral != sclk_map->peripheral || data0_map->peripheral != ssel_map->peripheral || data0_map->peripheral != dqs_map->peripheral) {
return {(int) NC, NC, (int) NC, NC, (int) NC, NC, (int) NC, NC, (int) NC, NC, (int) NC, NC, (int) NC, NC, (int) NC, NC, (int) NC};
}
return {data0_map->peripheral, data0_map->pin, data0_map->function, data1_map->pin, data1_map->function, data2_map->pin, data2_map->function, data3_map->pin, data3_map->function, data4_map->pin, data4_map->function, data5_map->pin, data5_map->function, data6_map->pin, data6_map->function, data7_map->pin, data7_map->function, sclk_map->pin, sclk_map->function, ssel_map->pin, ssel_map->function, dqs_map->pin, dqs_map->function};
}
#endif //DEVICE_OSPI
#else // STATIC_PINMAP_READY
#if DEVICE_PWMOUT
@ -358,6 +459,13 @@ MSTD_CONSTEXPR_FN_14 qspi_pinmap_t get_qspi_pinmap(const PinName data0, const Pi
}
#endif //DEVICE_QSPI
#if DEVICE_OSPI
MSTD_CONSTEXPR_FN_14 ospi_pinmap_t get_ospi_pinmap(const PinName data0, const PinName data1, const PinName data2, const PinName data3, const PinName data4, const PinName data5, const PinName data6, const PinName data7, const PinName sclk, const PinName ssel, const PinName dqs)
{
return {(int) NC, data0, (int) NC, data1, (int) NC, data2, (int) NC, data3, (int) NC, data4, (int) NC, data5, (int) NC, data6, (int) NC, data7, (int) NC, sclk, (int) NC, ssel, (int) NC, dqs, (int) NC};
}
#endif //DEVICE_OSPI
#endif // STATIC_PINMAP_READY
#endif // STATIC_PINMAP_H

View File

@ -93,4 +93,11 @@ MBED_WEAK qspi_status_t qspi_init_direct(qspi_t *obj, const qspi_pinmap_t *pinma
}
#endif
#if DEVICE_OSPI
MBED_WEAK ospi_status_t ospi_init_direct(ospi_t *obj, const ospi_pinmap_t *pinmap, uint32_t hz, uint8_t mode)
{
return ospi_init(obj, pinmap->data0_pin, pinmap->data1_pin, pinmap->data2_pin, pinmap->data3_pin, pinmap->data4_pin, pinmap->data5_pin, pinmap->data6_pin, pinmap->data7_pin, pinmap->sclk_pin, pinmap->ssel_pin, pinmap->dqs_pin, hz, mode);
}
#endif
#endif

View File

@ -0,0 +1,222 @@
/* mbed Microcontroller Library
* Copyright (c) 2018-2020 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_OSPI_FLASH_MX25LM51245G_H
#define MBED_OSPI_FLASH_MX25LM51245G_H
#define OSPI_FLASH_CHIP_STRING "macronix MX25LM51245G"
#define OSPI_CMD_RDID 0x9F
// Command for reading status register
#define OSPI_CMD_RDSR 0x05
// Command for reading configuration register
#define OSPI_CMD_RDCR0 0x15
#define OSPI_CMD_RDCR2 0x71
// Command for writing status/configuration register
#define OSPI_CMD_WRSR 0x01
#define OSPI_CMD_WRCR2 0x72
// Command for reading security register
#define OSPI_CMD_RDSCUR 0x2B
// Command for setting Reset Enable
#define OSPI_CMD_RSTEN 0x66
// Command for setting Reset
#define OSPI_CMD_RST 0x99
// Command for setting write enable
#define OSPI_CMD_WREN 0x06
// Command for setting write disable
#define OSPI_CMD_WRDI 0x04
// WRSR operations max time [us] (datasheet max time + 15%)
#define OSPI_WRSR_MAX_TIME 34500 // 30ms
// general wait max time [us]
#define OSPI_WAIT_MAX_TIME 100000 // 100ms
// Commands for writing (page programming)
// Only single/octal mode supported with this memory
// So only single 1-1-1 mode in this OSPI config
//#define OSPI_CMD_WRITE_1IO 0x02 // 1-1-1 mode
#define OSPI_CMD_WRITE_1IO 0x12 // 4 byte addr 1-1-1 mode
#define OSPI_CMD_WRITE_OPI 0x12 // 8-8-8 mode
// write operations max time [us] (datasheet max time + 15%)
#define OSPI_PAGE_PROG_MAX_TIME 11500 // 10ms
#define OSPI_PAGE_SIZE 256 // 256B
#define OSPI_SECTOR_SIZE 4096 // 4kB
#define OSPI_SECTOR_COUNT 2048
// Commands for reading
// Only single/octal mode supported with this memory
// So only single 1-1-1 mode in this OSPI config
#define OSPI_CMD_READ_1IO_FAST 0x0B // 1-1-1 mode
//#define OSPI_CMD_READ_1IO 0x03 // 1-1-1 mode
#define OSPI_CMD_READ_1IO 0x13 // 4 byte addr 1-1-1 mode
#define OSPI_CMD_READ_OPI 0xEC // 8-8-8 mode
#define OSPI_CMD_READ_DOPI 0xEE // 8D-8D-8D mode
#define OSPI_READ_1IO_DUMMY_CYCLE 0
#define OSPI_READ_FAST_DUMMY_CYCLE 8
#define OSPI_READ_8IO_DUMMY_CYCLE 20
// Commands for erasing
#define OSPI_CMD_ERASE_SECTOR 0x21 // 4kB
#define OSPI_CMD_ERASE_SECTOR_4B 0x21 // 4kB
//#define OSPI_CMD_ERASE_BLOCK_32 // not supported, only ersae block 64
#define OSPI_CMD_ERASE_BLOCK_64 0xD8 // 64kB
#define OSPI_CMD_ERASE_CHIP 0x60 // or 0xC7
// erase operations max time [us] (datasheet max time + 15%)
#define OSPI_ERASE_SECTOR_MAX_TIME 480000 // 400 ms
#define OSPI_ERASE_BLOCK_64_MAX_TIME 2400000 // 2s
// max frequency for basic rw operation (for fast mode)
#define OSPI_COMMON_MAX_FREQUENCY 66000000
#define OSPI_STATUS_REG_SIZE 2 //2 ??
#define OSPI_CONFIG_REG_0_SIZE 1
#define OSPI_CONFIG_REG_1_SIZE 2
#define OSPI_CONFIG_REG_2_SIZE 2 //1 byte in spi and sopi mode;2 byte in dopi
#define OSPI_SECURITY_REG_SIZE 1
#define OSPI_MAX_REG_SIZE 2
// 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) // Not supported
//#define STATUS_BIT_SRWD (1 << 7) // Not supported
// configuration register 0
// bit 0, 1, 2, 4, 5, 7 reserved
#define CONFIG0_BIT_TB (1 << 3) // Top/Bottom area protect
#define CONFIG2_OPI_EN_ADDR 0x00000000
// configuration register 2
#define CONFIG2_BIT_SOPI_EN (1 << 0) // sopi mode enable
#define CONFIG2_BIT_DOPI_EN (1 << 1) // dopi mode enable
#define CONFIG2_SPI_EN 0 // spi mode enable
#define OCTA_ENABLE() \
\
uint8_t reg_data[OSPI_CONFIG_REG_2_SIZE]; \
\
memset(reg_data, 0, OSPI_CONFIG_REG_2_SIZE); \
if (write_enable(ospi) != OSPI_STATUS_OK) { \
return OSPI_STATUS_ERROR; \
} \
\
reg_data[0] = CONFIG2_BIT_SOPI_EN; \
ospi.cmd.configure(MODE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8); \
if (write_config_register_2(OSPI_CMD_WRCR2, CONFIG2_OPI_EN_ADDR, \
reg_data, 1, ospi) != OSPI_STATUS_OK) { \
return OSPI_STATUS_ERROR; \
} \
ospi.cmd.configure(MODE_8_8_8, ADDR_SIZE_32, ALT_SIZE_8); \
WAIT_FOR(WRSR_MAX_TIME, ospi); \
memset(reg_data, 0, OSPI_CONFIG_REG_2_SIZE); \
\
if (read_config_register_2(OSPI_CMD_RDCR2, CONFIG2_OPI_EN_ADDR, \
reg_data, OSPI_CONFIG_REG_2_SIZE, ospi) != OSPI_STATUS_OK) { \
return OSPI_STATUS_ERROR; \
} \
return (reg_data[0] == CONFIG2_BIT_SOPI_EN ? \
OSPI_STATUS_OK : OSPI_STATUS_ERROR)
#define OCTA_DISABLE() \
\
uint8_t reg_data[OSPI_CONFIG_REG_2_SIZE]; \
\
memset(reg_data, 0, OSPI_CONFIG_REG_2_SIZE); \
if (write_enable(ospi) != OSPI_STATUS_OK) { \
return OSPI_STATUS_ERROR; \
} \
\
reg_data[0] = CONFIG2_SPI_EN; \
if (write_config_register_2(OSPI_CMD_WRCR2, CONFIG2_OPI_EN_ADDR, \
reg_data, 1, ospi) != OSPI_STATUS_OK) { \
return OSPI_STATUS_ERROR; \
} \
ospi.cmd.configure(MODE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8); \
WAIT_FOR(WRSR_MAX_TIME, ospi); \
memset(reg_data, 0, OSPI_CONFIG_REG_2_SIZE); \
if (read_config_register_2(OSPI_CMD_RDCR2, CONFIG2_OPI_EN_ADDR, \
reg_data, 1, ospi) != OSPI_STATUS_OK) { \
return OSPI_STATUS_ERROR; \
} \
return (reg_data[0] == CONFIG2_SPI_EN ? \
OSPI_STATUS_OK : OSPI_STATUS_ERROR)
#define OCTA_DTR_ENABLE() \
\
uint8_t reg_data[OSPI_CONFIG_REG_2_SIZE]; \
\
memset(reg_data, 0, OSPI_CONFIG_REG_2_SIZE); \
if (write_enable(ospi) != OSPI_STATUS_OK) { \
return OSPI_STATUS_ERROR; \
} \
\
reg_data[0] = CONFIG2_BIT_DOPI_EN; \
ospi.cmd.configure(MODE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8); \
if (write_config_register_2(OSPI_CMD_WRCR2, CONFIG2_OPI_EN_ADDR, \
reg_data, 1, ospi) != OSPI_STATUS_OK) { \
return OSPI_STATUS_ERROR; \
} \
ospi.cmd.configure(MODE_8D_8D_8D, ADDR_SIZE_32, ALT_SIZE_8); \
WAIT_FOR(WRSR_MAX_TIME, ospi); \
memset(reg_data, 0, OSPI_CONFIG_REG_2_SIZE); \
if (read_config_register_2(OSPI_CMD_RDCR2, CONFIG2_OPI_EN_ADDR, \
reg_data, OSPI_CONFIG_REG_2_SIZE, ospi) != OSPI_STATUS_OK) { \
return OSPI_STATUS_ERROR; \
} \
return (reg_data[0] == CONFIG2_BIT_DOPI_EN ? \
OSPI_STATUS_OK : OSPI_STATUS_ERROR)
#define OCTA_DTR_DISABLE() \
\
uint8_t reg_data[OSPI_CONFIG_REG_2_SIZE]; \
\
memset(reg_data, 0, OSPI_CONFIG_REG_2_SIZE); \
if (write_enable(ospi) != OSPI_STATUS_OK) { \
return OSPI_STATUS_ERROR; \
} \
\
reg_data[0] = CONFIG2_SPI_EN; \
if (write_config_register_2(OSPI_CMD_WRCR2, CONFIG2_OPI_EN_ADDR, \
reg_data, OSPI_CONFIG_REG_2_SIZE, ospi) != OSPI_STATUS_OK) { \
return OSPI_STATUS_ERROR; \
} \
ospi.cmd.configure(MODE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8); \
WAIT_FOR(WRSR_MAX_TIME, ospi); \
memset(reg_data, 0, OSPI_CONFIG_REG_2_SIZE); \
if (read_config_register_2(OSPI_CMD_RDCR2, CONFIG2_OPI_EN_ADDR, \
reg_data, OSPI_CONFIG_REG_2_SIZE, ospi) != OSPI_STATUS_OK) { \
return OSPI_STATUS_ERROR; \
} \
return (reg_data[0] == CONFIG2_SPI_EN ? \
OSPI_STATUS_OK : OSPI_STATUS_ERROR)
#endif // MBED_OSPI_FLASH_MX25LM51245G_H

View File

@ -0,0 +1,26 @@
/* mbed Microcontroller Library
* Copyright (c) 2018-2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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_MX25LM51245G)
#include "MX25LM51245G_config.h"
#endif
#endif // MBED_FLASH_CONFIGS_H

View File

@ -0,0 +1,645 @@
/* mbed Microcontroller Library
* Copyright (c) 2018-2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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_OSPI
#error [NOT_SUPPORTED] OSPI not supported for this target
#else
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "ospi_test.h"
#include "ospi_test_utils.h"
#include "mbed.h"
#include "ospi_api.h"
#include "hal/us_ticker_api.h"
#if !defined(OSPI_FLASH_CHIP_STRING)
#error [NOT_SUPPORTED] OSPI test not supported for this target
#else
using namespace utest::v1;
// uncomment to enable verbose mode
//#define OSPI_TEST_LOG_DATA
//#define OSPI_TEST_LOG_FLASH_TIME
//#define OSPI_TEST_LOG_FLASH_STATUS
#ifndef OSPI_MIN_FREQUENCY
#define OSPI_MIN_FREQUENCY 1000000
#endif
// max write size is usually page size
#define DATA_SIZE_256 (OSPI_PAGE_SIZE)
#define DATA_SIZE_1024 (OSPI_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 4
// 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 OSPI pins as integers thus conversion needed
#define OPIN_0 static_cast<PinName>(MBED_CONF_DRIVERS_OSPI_IO0)
#define OPIN_1 static_cast<PinName>(MBED_CONF_DRIVERS_OSPI_IO1)
#define OPIN_2 static_cast<PinName>(MBED_CONF_DRIVERS_OSPI_IO2)
#define OPIN_3 static_cast<PinName>(MBED_CONF_DRIVERS_OSPI_IO3)
#define OPIN_4 static_cast<PinName>(MBED_CONF_DRIVERS_OSPI_IO4)
#define OPIN_5 static_cast<PinName>(MBED_CONF_DRIVERS_OSPI_IO5)
#define OPIN_6 static_cast<PinName>(MBED_CONF_DRIVERS_OSPI_IO6)
#define OPIN_7 static_cast<PinName>(MBED_CONF_DRIVERS_OSPI_IO7)
#define QSCK static_cast<PinName>(MBED_CONF_DRIVERS_OSPI_SCK)
#define QCSN static_cast<PinName>(MBED_CONF_DRIVERS_OSPI_CSN)
#define DQS static_cast<PinName>(MBED_CONF_DRIVERS_OSPI_DQS)
static uint32_t gen_flash_address()
{
srand(ticker_read(get_us_ticker_data()));
uint32_t address = (((uint32_t)rand()) % OSPI_SECTOR_COUNT) * OSPI_SECTOR_SIZE;
address &= 0xFFFFFF; // Ensure address is within 24 bits so as to not have to deal with 4-byte addressing
return address;
}
static void log_data(const char *str, uint8_t *data, uint32_t size)
{
utest_printf("%s: ", str);
for (uint32_t j = 0; j < size; j++) {
utest_printf("%02X ", data[j]);
}
utest_printf("\r\n");
}
static void _ospi_write_read_test(Ospi &ospi, ospi_bus_width_t write_inst_width, ospi_bus_width_t write_addr_width,
ospi_bus_width_t write_data_width, ospi_bus_width_t write_alt_width, uint32_t write_cmd,
ospi_address_size_t write_addr_size, ospi_alt_size_t write_alt_size,
uint32_t write_count, ospi_bus_width_t read_inst_width, ospi_bus_width_t read_addr_width,
ospi_bus_width_t read_data_width, ospi_bus_width_t read_alt_width, uint32_t read_cmd,
int read_dummy_cycles, ospi_address_size_t read_addr_size, ospi_alt_size_t read_alt_size,
uint32_t read_count, uint32_t test_count, uint32_t data_size,
uint32_t flash_addr)
{
ospi_status_t ret = OSPI_STATUS_OK;
Timer timer;
int erase_time = 0, write_time = 0, read_time = 0;
size_t buf_len = data_size;
for (uint32_t tc = 0; tc < test_count; tc++) {
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(ospi);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
timer.reset();
timer.start();
ret = erase(SECTOR_ERASE, flash_addr, ospi);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
WAIT_FOR(SECTOR_ERASE_MAX_TIME, ospi);
timer.stop();
erase_time = timer.read_us();
// switching to extended-SPI/DPI/QPI mode here for write operation
// for DPI/QPI ospi.cmd is automatically switched to 2_2_2/4_4_4 mode
ret = mode_enable(ospi, write_inst_width, write_addr_width, write_data_width);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
const uint32_t write_size = data_size / write_count;
for (uint32_t wc = 0, write_start = flash_addr; wc < write_count; wc++, write_start += write_size) {
ret = write_enable(ospi);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
timer.reset();
timer.start();
buf_len = write_size;
ospi.cmd.configure(write_inst_width, write_addr_width, write_data_width, write_alt_width, write_addr_size, write_alt_size);
ospi.cmd.build(write_cmd, write_start);
ret = ospi_write(&ospi.handle, ospi.cmd.get(), tx_buf + wc * write_size, &buf_len);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
TEST_ASSERT_EQUAL(write_size, buf_len);
if (is_extended_mode(write_inst_width, write_addr_width, write_data_width)) {
// on some flash chips in extended-SPI mode, control commands works only in 1-1-1 mode
// so switching back to 1-1-1 mode
ospi.cmd.configure(MODE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8);
}
WAIT_FOR(PAGE_PROG_MAX_TIME, ospi);
timer.stop();
write_time = timer.read_us();
}
// switching back to single channel SPI
ret = mode_disable(ospi, write_inst_width, write_addr_width, write_data_width);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
// switching to extended-SPI/DPI/QPI mode here for read operation
// for DPI/QPI ospi.cmd is automatically switched to 2_2_2/4_4_4 mode
ret = mode_enable(ospi, read_inst_width, read_addr_width, read_data_width);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
memset(rx_buf, 0, sizeof(rx_buf));
const uint32_t read_size = data_size / read_count;
ospi.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;
ospi.cmd.build(read_cmd, read_start);
ret = ospi_read(&ospi.handle, ospi.cmd.get(), rx_buf + rc * read_size, &buf_len);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
TEST_ASSERT_EQUAL(read_size, buf_len);
timer.stop();
read_time = timer.read_us();
}
ospi.cmd.set_dummy_cycles(0);
if (is_extended_mode(read_inst_width, read_addr_width, read_data_width)) {
// on some flash chips in extended-SPI mode, control commands works only in 1-1-1 mode
// so switching back to 1-1-1 mode
ospi.cmd.configure(MODE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8);
}
// switching back to single channel SPI
ret = mode_disable(ospi, read_inst_width, read_addr_width, read_data_width);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
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);
utest_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 OSPI_TEST_LOG_FLASH_TIME
utest_printf("erase/write/read time: %d/%d/%d [us]\r\n", erase_time, write_time, read_time);
#endif
#ifdef OSPI_TEST_LOG_DATA
log_data("tx data", tx_buf, data_size);
log_data("rx data", rx_buf, data_size);
utest_printf("rx/tx data match\r\n");
#endif
}
}
template < ospi_bus_width_t write_inst_width,
ospi_bus_width_t write_addr_width,
ospi_bus_width_t write_data_width,
ospi_bus_width_t write_alt_width,
unsigned int write_cmd,
ospi_address_size_t write_addr_size,
ospi_alt_size_t write_alt_size,
uint32_t write_count,
ospi_bus_width_t read_inst_width,
ospi_bus_width_t read_addr_width,
ospi_bus_width_t read_data_width,
ospi_bus_width_t read_alt_width,
unsigned int read_cmd,
int read_dummy_cycles,
ospi_address_size_t read_addr_size,
ospi_alt_size_t read_alt_size,
int frequency,
uint32_t read_count,
uint32_t test_count,
uint32_t data_size,
uint32_t flash_addr>
void ospi_write_read_test(void)
{
ospi_status_t ret;
Ospi ospi;
uint32_t addr = flash_addr;
if (addr == 0) {
// if no specified address selected, use random one to extend flash life
addr = gen_flash_address();
}
ospi_init(&ospi.handle, OPIN_0, OPIN_1, OPIN_2, OPIN_3, OPIN_4, OPIN_5, OPIN_6, OPIN_7, QSCK, QCSN, DQS, OSPI_COMMON_MAX_FREQUENCY, 0);
ret = ospi_frequency(&ospi.handle, frequency);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
ospi.cmd.configure(MODE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8);
flash_init(ospi);
// switch memory to high performance mode (if available)
ret = fast_mode_enable(ospi);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
#ifdef OSPI_TEST_LOG_FLASH_STATUS
log_register(STATUS_REG, OSPI_STATUS_REG_SIZE, ospi, "Status register");
log_register(CONFIG_REG0, OSPI_CONFIG_REG_0_SIZE, ospi, "Config register 0");
#ifdef CONFIG_REG1
log_register(CONFIG_REG1, OSPI_CONFIG_REG_1_SIZE, ospi, "Config register 1");
#endif
#ifdef CONFIG_REG2
log_register(CONFIG_REG2, OSPI_CONFIG_REG_2_SIZE, ospi, "Config register 2");
#endif
#endif
_ospi_write_read_test(ospi, write_inst_width, write_addr_width, write_data_width, write_alt_width, write_cmd,
write_addr_size, write_alt_size, 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_count, test_count,
data_size, addr);
ret = fast_mode_disable(ospi);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
ospi_free(&ospi.handle);
}
void ospi_init_free_test(void)
{
Ospi ospi;
ospi_status_t ret;
ret = ospi_init(&ospi.handle, OPIN_0, OPIN_1, OPIN_2, OPIN_3, OPIN_4, OPIN_5, OPIN_6, OPIN_7, QSCK, QCSN, DQS, OSPI_COMMON_MAX_FREQUENCY, 0);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
ret = ospi_free(&ospi.handle);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
ret = ospi_init(&ospi.handle, OPIN_0, OPIN_1, OPIN_2, OPIN_3, OPIN_4, OPIN_5, OPIN_6, OPIN_7, QSCK, QCSN, DQS, OSPI_COMMON_MAX_FREQUENCY, 0);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
ret = ospi_free(&ospi.handle);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
ret = ospi_init(&ospi.handle, OPIN_0, OPIN_1, OPIN_2, OPIN_3, OPIN_4, OPIN_5, OPIN_6, OPIN_7, QSCK, QCSN, DQS, OSPI_COMMON_MAX_FREQUENCY, 0);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
ret = ospi_free(&ospi.handle);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
ret = ospi_init(&ospi.handle, OPIN_0, OPIN_1, OPIN_2, OPIN_3, OPIN_4, OPIN_5, OPIN_6, OPIN_7, QSCK, QCSN, DQS, OSPI_COMMON_MAX_FREQUENCY, 0);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
// check if the memory is working properly
ospi.cmd.configure(MODE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8);
flash_init(ospi);
#ifdef OSPI_TEST_LOG_FLASH_STATUS
log_register(STATUS_REG, OSPI_STATUS_REG_SIZE, ospi, "Status register");
log_register(CONFIG_REG0, OSPI_CONFIG_REG_0_SIZE, ospi, "Config register 0");
#ifdef CONFIG_REG1
log_register(CONFIG_REG1, OSPI_CONFIG_REG_1_SIZE, ospi, "Config register 1");
#endif
#ifdef CONFIG_REG2
log_register(CONFIG_REG2, OSPI_CONFIG_REG_2_SIZE, ospi, "Config register 2");
#endif
#endif
_ospi_write_read_test(ospi, WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS);
ospi_free(&ospi.handle);
}
void ospi_frequency_test(void)
{
Ospi ospi;
ospi_status_t ret;
int freq = OSPI_COMMON_MAX_FREQUENCY;
ret = ospi_init(&ospi.handle, OPIN_0, OPIN_1, OPIN_2, OPIN_3, OPIN_4, OPIN_5, OPIN_6, OPIN_7, QSCK, QCSN, DQS, freq, 0);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
while (ret == OSPI_STATUS_OK && freq >= OSPI_MIN_FREQUENCY) {
// check if the memory is working properly
ospi.cmd.configure(MODE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8);
ret = ospi_frequency(&ospi.handle, freq);
flash_init(ospi);
_ospi_write_read_test(ospi, WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS);
utest_printf("frequency setting %d [Hz] - OK\r\n", freq);
freq /= 2;
}
ospi_free(&ospi.handle);
}
void ospi_memory_id_test()
{
utest_printf("*** %s memory config loaded ***\r\n", OSPI_FLASH_CHIP_STRING);
}
Case cases[] = {
Case("ospi memory id test", ospi_memory_id_test),
Case("ospi init/free test", ospi_init_free_test),
Case("ospi frequency setting test", ospi_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)
// 1-1-1 - single channel SPI
// 1-1-2 - Dual data (extended SPI)
// 1-2-2 - Dual I/O (extended SPI)
// 1-1-4 - Quad data (extended SPI)
// 1-4-4 - Quad I/O (extended SPI)
// 2-2-2 - DPI (multi-channel SPI)
// 4-4-4 - QPI (multi-channel SPI)
Case("ospi write(1-1-1)/x1 read(1-1-1)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x4 read(1-1-1)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(1-1-1)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(1-1-1)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_1_1_2
Case("ospi write(1-1-1)/x1 read(1-1-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x4 read(1-1-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(1-1-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(1-1-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef READ_1_2_2
Case("ospi write(1-1-1)/x1 read(1-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x4 read(1-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(1-2-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(1-2-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef READ_2_2_2
Case("ospi write(1-1-1)/x1 read(2-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x4 read(2-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(2-2-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(2-2-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef READ_1_1_4
Case("ospi write(1-1-1)/x1 read(1-1-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x4 read(1-1-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(1-1-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(1-1-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef READ_1_4_4
Case("ospi write(1-1-1)/x1 read(1-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x4 read(1-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(1-4-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(1-4-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef READ_4_4_4
Case("ospi write(1-1-1)/x1 read(4-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x4 read(4-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(4-4-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-1)/x1 read(4-4-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef WRITE_1_2_2
Case("ospi write(1-2-2)/x1 read(1-1-1)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x4 read(1-1-1)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(1-1-1)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(1-1-1)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(1-1-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x4 read(1-1-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(1-1-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(1-1-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(1-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x4 read(1-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(1-2-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(1-2-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_2_2_2
Case("ospi write(1-2-2)/x1 read(2-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x4 read(2-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(2-2-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(2-2-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef READ_1_1_4
Case("ospi write(1-2-2)/x1 read(1-1-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x4 read(1-1-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(1-1-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(1-1-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
Case("ospi write(1-2-2)/x1 read(1-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x4 read(1-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(1-4-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(1-4-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_4_4_4
Case("ospi write(1-2-2)/x1 read(4-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x4 read(4-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(4-4-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-2-2)/x1 read(4-4-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#endif
#ifdef WRITE_2_2_2
Case("ospi write(2-2-2)/x1 read(1-1-1)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x4 read(1-1-1)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(1-1-1)/x4 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(1-1-1)/x1 repeat/x4 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(1-1-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x4 read(1-1-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(1-1-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(1-1-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(1-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x4 read(1-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(1-2-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(1-2-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_2_2_2
Case("ospi write(2-2-2)/x1 read(2-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x4 read(2-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(2-2-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(2-2-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef READ_1_1_4
Case("ospi write(2-2-2)/x1 read(1-1-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x4 read(1-1-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(1-1-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(1-1-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
Case("ospi write(2-2-2)/x1 read(1-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x4 read(1-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(1-4-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(1-4-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_4_4_4
Case("ospi write(2-2-2)/x1 read(4-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x4 read(4-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(4-4-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(2-2-2)/x1 read(4-4-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#endif
#ifdef WRITE_1_1_4
Case("ospi write(1-1-4)/x1 read(1-1-1)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x4 read(1-1-1)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(1-1-1)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(1-1-1)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(1-1-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x4 read(1-1-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(1-1-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(1-1-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(1-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x4 read(1-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(1-2-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(1-2-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_2_2_2
Case("ospi write(1-1-4)/x1 read(2-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x4 read(2-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(2-2-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(2-2-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef READ_1_1_4
Case("ospi write(1-1-4)/x1 read(1-1-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x4 read(1-1-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(1-1-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(1-1-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
Case("ospi write(1-1-4)/x1 read(1-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x4 read(1-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(1-4-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(1-4-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_4_4_4
Case("ospi write(1-1-4)/x1 read(4-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x4 read(4-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(4-4-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-1-4)/x1 read(4-4-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#endif
#ifdef WRITE_1_4_4
Case("ospi write(1-4-4)/x1 read(1-1-1)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x4 read(1-1-1)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(1-1-1)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(1-1-1)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(1-1-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x4 read(1-1-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(1-1-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(1-1-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(1-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x4 read(1-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(1-2-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(1-2-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_2_2_2
Case("ospi write(1-4-4)/x1 read(2-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x4 read(2-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(2-2-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(2-2-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef READ_1_1_4
Case("ospi write(1-4-4)/x1 read(1-1-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x4 read(1-1-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(1-1-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(1-1-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
Case("ospi write(1-4-4)/x1 read(1-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x4 read(1-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(1-4-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(1-4-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_4_4_4
Case("ospi write(1-4-4)/x1 read(4-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x4 read(4-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(4-4-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(1-4-4)/x1 read(4-4-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#endif
#ifdef WRITE_4_4_4
Case("ospi write(4-4-4)/x1 read(1-1-1)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x4 read(1-1-1)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(1-1-1)/x4 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(1-1-1)/x1 repeat/x4 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(1-1-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x4 read(1-1-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(1-1-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(1-1-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(1-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x4 read(1-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(1-2-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(1-2-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_2_2_2
Case("ospi write(4-4-4)/x1 read(2-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x4 read(2-2-2)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(2-2-2)/x4 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(2-2-2)/x1 repeat/x4 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef READ_1_1_4
Case("ospi write(4-4-4)/x1 read(1-1-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x4 read(1-1-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(1-1-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(1-1-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
Case("ospi write(4-4-4)/x1 read(1-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x4 read(1-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(1-4-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(1-4-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_4_4_4
Case("ospi write(4-4-4)/x1 read(4-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x4 read(4-4-4)/x1 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(4-4-4)/x4 repeat/x1 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(4-4-4)/x1 read(4-4-4)/x1 repeat/x4 test", ospi_write_read_test<WRITE_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#endif
#ifdef READ_8_8_8
Case("ospi write(8_8_8)/x1 read(8_8_8)/x1 repeat/x1 test", ospi_write_read_test<WRITE_8_8_8, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_8_8_8, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(8_8_8)/x4 read(8_8_8)/x1 repeat/x1 test", ospi_write_read_test<WRITE_8_8_8, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_8_8_8, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(8_8_8)/x1 read(8_8_8)/x4 repeat/x1 test", ospi_write_read_test<WRITE_8_8_8, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_8_8_8, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(8_8_8)/x1 read(8_8_8)/x1 repeat/x4 test", ospi_write_read_test<WRITE_8_8_8, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_8_8_8, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef READ_8D_8D_8D
Case("ospi write(8D_8D_8D)/x1 read(8D_8D_8D)/x1 repeat/x1 test", ospi_write_read_test<WRITE_8D_8D_8D, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_8D_8D_8D, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(8D_8D_8D)/x4 read(8D_8D_8D)/x1 repeat/x1 test", ospi_write_read_test<WRITE_8D_8D_8D, ADDR_SIZE_32, ALT_SIZE_8, WRITE_MULTIPLE, READ_8D_8D_8D, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("ospi write(8D_8D_8D)/x1 read(8D_8D_8D)/x4 repeat/x1 test", ospi_write_read_test<WRITE_8D_8D_8D, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_8D_8D_8D, ADDR_SIZE_32, ALT_SIZE_8, OSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("ospi write(8D_8D_8D)/x1 read(8D_8D_8D)/x1 repeat/x4 test", ospi_write_read_test<WRITE_8D_8D_8D, ADDR_SIZE_32, ALT_SIZE_8, WRITE_SINGLE, READ_8D_8D_8D, ADDR_SIZE_32, ALT_SIZE_8, OSPI_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(180, "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);
}
#endif // !defined(OSPI_FLASH_CHIP_STRING)
#endif // !DEVICE_OSPI

View File

@ -0,0 +1,102 @@
/* mbed Microcontroller Library
* Copyright (c) 2018-2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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_ospi
* @{
* \defgroup hal_ospi_tests Tests
* OSPI tests of the HAL.
* @{
*/
#ifndef MBED_OSPI_TEST_H
#define MBED_OSPI_TEST_H
#include "ospi_test_utils.h"
#include "ospi_api.h"
#if DEVICE_OSPI
/** Test that ospi_init/ospi_free can be called multiple times.
*
* Given board provides OSPI.
* When ospi_init/ospi_free is called multiple times.
* Then ospi_init/ospi_free are successfully performed (no exception is generated).
*
*/
void ospi_init_free_test(void);
/** Test ospi frequency setting.
*
* Given board provides OSPI, with OSPI already initialized.
* When set OSPI frequency.
* Then freguency setting is successfully performed (no exception is generated).
*
*/
void ospi_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 OSPI, with OSPI 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 OSPI, with OSPI 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 OSPI, with OSPI 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 OSPI, with OSPI 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 < ospi_bus_width_t write_inst_width,
ospi_bus_width_t write_addr_width,
ospi_bus_width_t write_data_width,
ospi_bus_width_t write_alt_width,
unsigned int write_cmd,
ospi_address_size_t write_addr_size,
ospi_alt_size_t write_alt_size,
uint32_t write_count,
ospi_bus_width_t read_inst_width,
ospi_bus_width_t read_addr_width,
ospi_bus_width_t read_data_width,
ospi_bus_width_t read_alt_width,
unsigned int read_cmd,
int read_dummy_cycles,
ospi_address_size_t read_addr_size,
ospi_alt_size_t read_alt_size,
int frequency,
uint32_t read_count,
uint32_t test_count,
uint32_t data_size,
uint32_t flash_addr>
void ospi_write_read_test(void);
#endif
#endif
/** @}*/
/** @}*/

View File

@ -0,0 +1,415 @@
/* mbed Microcontroller Library
* Copyright (c) 2018-2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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 "ospi_test_utils.h"
#include "utest/utest.h"
#include "hal/ospi_api.h"
#include "hal/us_ticker_api.h"
#include "unity/unity.h"
#include <string.h> // for memset
#include "flash_configs/flash_configs.h"
#include "mbed.h"
static ospi_status_t extended_enable(Ospi &ospi);
static ospi_status_t extended_disable(Ospi &ospi);
static ospi_status_t dual_enable(Ospi &ospi);
static ospi_status_t dual_disable(Ospi &ospi);
static ospi_status_t quad_enable(Ospi &ospi);
static ospi_status_t quad_disable(Ospi &ospi);
static ospi_status_t octa_enable(Ospi &ospi);
static ospi_status_t octa_disable(Ospi &ospi);
static ospi_status_t octa_dtr_enable(Ospi &ospi);
static ospi_status_t octa_dtr_disable(Ospi &ospi);
void OspiCommand::configure(ospi_bus_width_t inst_width, ospi_bus_width_t addr_width,
ospi_bus_width_t data_width, ospi_bus_width_t alt_width,
ospi_address_size_t addr_size, ospi_alt_size_t alt_size,
int dummy_cycles)
{
memset(&_cmd, 0, sizeof(ospi_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 OspiCommand::set_dummy_cycles(int dummy_cycles)
{
_cmd.dummy_count = dummy_cycles;
}
void OspiCommand::build(int instruction, int address, int alt)
{
_cmd.instruction.disabled = (instruction == -1);
if (!_cmd.instruction.disabled) {
_cmd.instruction.value = instruction;
}
_cmd.address.disabled = (address == OSPI_NONE);
if (!_cmd.address.disabled) {
_cmd.address.value = address;
}
_cmd.alt.disabled = (alt == OSPI_NONE);
if (!_cmd.alt.disabled) {
_cmd.alt.value = alt;
}
if ((_cmd.instruction.bus_width == OSPI_CFG_BUS_OCTA) || (_cmd.instruction.bus_width == OSPI_CFG_BUS_OCTA_DTR)) {
if (instruction == STATUS_REG) {
_cmd.address.disabled = 0;
_cmd.address.value = 0;
_cmd.dummy_count = 4;
} else if (instruction == OSPI_CMD_RDCR2) {
_cmd.dummy_count = 4;
} else if ((instruction == OSPI_CMD_READ_OPI) || (instruction == OSPI_CMD_READ_DOPI)) {
_cmd.dummy_count = 20;
} else {
_cmd.dummy_count = 0;
}
}
}
ospi_command_t *OspiCommand::get()
{
return &_cmd;
}
ospi_status_t read_register(uint32_t cmd, uint8_t *buf, uint32_t size, Ospi &q)
{
q.cmd.build(cmd);
return ospi_command_transfer(&q.handle, q.cmd.get(), NULL, 0, buf, size);
}
ospi_status_t write_register(uint32_t cmd, uint8_t *buf, uint32_t size, Ospi &q)
{
q.cmd.build(cmd);
return ospi_command_transfer(&q.handle, q.cmd.get(), buf, size, NULL, 0);
}
ospi_status_t read_config_register_2(uint32_t cmd, uint32_t addr, uint8_t *buf, uint32_t size, Ospi &q)
{
q.cmd.build(cmd, addr);
return ospi_command_transfer(&q.handle, q.cmd.get(), NULL, 0, buf, size);
}
ospi_status_t write_config_register_2(uint32_t cmd, uint32_t addr, uint8_t *buf, uint32_t size, Ospi &q)
{
q.cmd.build(cmd, addr);
return ospi_command_transfer(&q.handle, q.cmd.get(), buf, size, NULL, 0);
}
OspiStatus flash_wait_for(uint32_t time_us, Ospi &ospi)
{
uint8_t reg[OSPI_STATUS_REG_SIZE];
ospi_status_t ret;
uint32_t curr_time;
const ticker_data_t *const ticker = get_us_ticker_data();
const uint32_t start = ticker_read(ticker);
memset(reg, 255, OSPI_STATUS_REG_SIZE);
do {
ret = read_register(STATUS_REG, reg, OSPI_STATUS_REG_SIZE, ospi);
curr_time = ticker_read(ticker);
} while (((reg[0] & STATUS_BIT_WIP) != 0) && ((curr_time - start) < time_us));
if (((reg[0] & STATUS_BIT_WIP) == 0) && (ret == OSPI_STATUS_OK)) {
return sOK;
} else if (ret != OSPI_STATUS_OK) {
return sError;
} else if ((curr_time - start) >= time_us) {
return sTimeout;
}
return sUnknown;
}
void flash_init(Ospi &ospi)
{
uint8_t status[OSPI_STATUS_REG_SIZE];
ospi_status_t ret;
ospi.cmd.build(OSPI_CMD_RDSR);
ret = ospi_command_transfer(&ospi.handle, ospi.cmd.get(), NULL, 0, status, OSPI_STATUS_REG_SIZE);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
// Only do reset enable if device needs it
if (OSPI_CMD_RSTEN != 0) {
ospi.cmd.build(OSPI_CMD_RSTEN);
ret = ospi_command_transfer(&ospi.handle, ospi.cmd.get(), NULL, 0, NULL, 0);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
WAIT_FOR(WRSR_MAX_TIME, ospi);
}
ospi.cmd.build(OSPI_CMD_RST);
ret = ospi_command_transfer(&ospi.handle, ospi.cmd.get(), NULL, 0, NULL, 0);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
WAIT_FOR(WAIT_MAX_TIME, ospi);
// Zero out status register to attempt to clear block protection bits
uint8_t blanks[OSPI_STATUS_REG_SIZE] = {0};
ospi.cmd.build(OSPI_CMD_WREN);
ret = ospi_command_transfer(&ospi.handle, ospi.cmd.get(), NULL, 0, NULL, 0);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
ospi.cmd.build(OSPI_CMD_WRSR);
ret = ospi_command_transfer(&ospi.handle, ospi.cmd.get(), blanks, 1, NULL, 0);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
WAIT_FOR(WRSR_MAX_TIME, ospi);
}
ospi_status_t write_enable(Ospi &ospi)
{
uint8_t reg[OSPI_STATUS_REG_SIZE];
ospi.cmd.build(OSPI_CMD_WREN);
if (ospi_command_transfer(&ospi.handle, ospi.cmd.get(), NULL, 0, NULL, 0) != OSPI_STATUS_OK) {
return OSPI_STATUS_ERROR;
}
WAIT_FOR(WRSR_MAX_TIME, ospi);
memset(reg, 0, OSPI_STATUS_REG_SIZE);
if (read_register(STATUS_REG, reg, OSPI_STATUS_REG_SIZE, ospi) != OSPI_STATUS_OK) {
return OSPI_STATUS_ERROR;
}
return ((reg[0] & STATUS_BIT_WEL) != 0 ? OSPI_STATUS_OK : OSPI_STATUS_ERROR);
}
ospi_status_t write_disable(Ospi &ospi)
{
uint8_t reg[OSPI_STATUS_REG_SIZE];
ospi.cmd.build(OSPI_CMD_WRDI);
if (ospi_command_transfer(&ospi.handle, ospi.cmd.get(), NULL, 0, NULL, 0) != OSPI_STATUS_OK) {
return OSPI_STATUS_ERROR;
}
WAIT_FOR(WRSR_MAX_TIME, ospi);
memset(reg, 0, OSPI_STATUS_REG_SIZE);
if (read_register(STATUS_REG, reg, OSPI_STATUS_REG_SIZE, ospi) != OSPI_STATUS_OK) {
return OSPI_STATUS_ERROR;
}
return ((reg[0] & STATUS_BIT_WEL) == 0 ? OSPI_STATUS_OK : OSPI_STATUS_ERROR);
}
void log_register(uint32_t cmd, uint32_t reg_size, Ospi &ospi, const char *str)
{
ospi_status_t ret;
static uint8_t reg[OSPI_MAX_REG_SIZE];
ret = read_register(cmd, reg, reg_size, ospi);
TEST_ASSERT_EQUAL(OSPI_STATUS_OK, ret);
for (uint32_t j = 0; j < reg_size; j++) {
utest_printf("%s byte %u (MSB first): ", str != NULL ? str : "", j);
for (int i = 0; i < 8; i++) {
utest_printf("%s ", ((reg[j] & (1 << (7 - i))) & 0xFF) == 0 ? "0" : "1");
}
utest_printf("\r\n");
}
}
ospi_status_t erase(uint32_t erase_cmd, uint32_t flash_addr, Ospi &ospi)
{
ospi.cmd.build(erase_cmd, flash_addr);
return ospi_command_transfer(&ospi.handle, ospi.cmd.get(), NULL, 0, NULL, 0);
}
ospi_status_t mode_enable(Ospi &ospi, ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width)
{
if (is_extended_mode(inst_width, addr_width, data_width)) {
return extended_enable(ospi);
} else if (is_dual_mode(inst_width, addr_width, data_width)) {
return dual_enable(ospi);
} else if (is_quad_mode(inst_width, addr_width, data_width)) {
return quad_enable(ospi);
} else if (is_octa_mode(inst_width, addr_width, data_width)) {
return octa_enable(ospi);
} else if (is_octa_dtr_mode(inst_width, addr_width, data_width)) {
return octa_dtr_enable(ospi);
} else {
return OSPI_STATUS_OK;
}
}
ospi_status_t mode_disable(Ospi &ospi, ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width)
{
if (is_extended_mode(inst_width, addr_width, data_width)) {
return extended_disable(ospi);
} else if (is_dual_mode(inst_width, addr_width, data_width)) {
return dual_disable(ospi);
} else if (is_quad_mode(inst_width, addr_width, data_width)) {
return quad_disable(ospi);
} else if (is_octa_mode(inst_width, addr_width, data_width)) {
return octa_disable(ospi);
} else if (is_octa_dtr_mode(inst_width, addr_width, data_width)) {
return octa_dtr_disable(ospi);
} else {
return OSPI_STATUS_OK;
}
}
static ospi_status_t extended_enable(Ospi &ospi)
{
#ifdef EXTENDED_SPI_ENABLE
EXTENDED_SPI_ENABLE();
#else
return OSPI_STATUS_OK;
#endif
}
static ospi_status_t extended_disable(Ospi &ospi)
{
#ifdef EXTENDED_SPI_DISABLE
EXTENDED_SPI_DISABLE();
#else
return OSPI_STATUS_OK;
#endif
}
static ospi_status_t dual_enable(Ospi &ospi)
{
#ifdef DUAL_ENABLE
DUAL_ENABLE();
#else
return OSPI_STATUS_OK;
#endif
}
static ospi_status_t dual_disable(Ospi &ospi)
{
#ifdef DUAL_DISABLE
DUAL_DISABLE();
#else
return OSPI_STATUS_OK;
#endif
}
static ospi_status_t quad_enable(Ospi &ospi)
{
#ifdef QUAD_ENABLE
QUAD_ENABLE();
#else
return OSPI_STATUS_OK;
#endif
}
static ospi_status_t quad_disable(Ospi &ospi)
{
#ifdef QUAD_DISABLE
QUAD_DISABLE();
#else
return OSPI_STATUS_OK;
#endif
}
static ospi_status_t octa_enable(Ospi &ospi)
{
#ifdef OCTA_ENABLE
OCTA_ENABLE();
#else
return OSPI_STATUS_OK;
#endif
}
static ospi_status_t octa_disable(Ospi &ospi)
{
#ifdef OCTA_DISABLE
OCTA_DISABLE();
#else
return OSPI_STATUS_OK;
#endif
}
static ospi_status_t octa_dtr_enable(Ospi &ospi)
{
#ifdef OCTA_DTR_ENABLE
OCTA_DTR_ENABLE();
#else
return OSPI_STATUS_OK;
#endif
}
static ospi_status_t octa_dtr_disable(Ospi &ospi)
{
#ifdef OCTA_DTR_DISABLE
OCTA_DTR_DISABLE();
#else
return OSPI_STATUS_OK;
#endif
}
ospi_status_t fast_mode_enable(Ospi &ospi)
{
#ifdef FAST_MODE_ENABLE
FAST_MODE_ENABLE();
#else
return OSPI_STATUS_OK;
#endif
}
ospi_status_t fast_mode_disable(Ospi &ospi)
{
#ifdef FAST_MODE_DISABLE
FAST_MODE_DISABLE();
#else
return OSPI_STATUS_OK;
#endif
}
bool is_extended_mode(ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width)
{
return (inst_width == OSPI_CFG_BUS_SINGLE) && ((addr_width != OSPI_CFG_BUS_SINGLE) || (data_width != OSPI_CFG_BUS_SINGLE));
}
bool is_dual_mode(ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width)
{
return (inst_width == OSPI_CFG_BUS_DUAL) && (addr_width == OSPI_CFG_BUS_DUAL) && (data_width == OSPI_CFG_BUS_DUAL);
}
bool is_quad_mode(ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width)
{
return (inst_width == OSPI_CFG_BUS_QUAD) && (addr_width == OSPI_CFG_BUS_QUAD) && (data_width == OSPI_CFG_BUS_QUAD);
}
bool is_octa_mode(ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width)
{
return (inst_width == OSPI_CFG_BUS_OCTA) && (addr_width == OSPI_CFG_BUS_OCTA) && (data_width == OSPI_CFG_BUS_OCTA);
}
bool is_octa_dtr_mode(ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width)
{
return (inst_width == OSPI_CFG_BUS_OCTA_DTR) && (addr_width == OSPI_CFG_BUS_OCTA_DTR) && (data_width == OSPI_CFG_BUS_OCTA_DTR);
}

View File

@ -0,0 +1,186 @@
/* mbed Microcontroller Library
* Copyright (c) 2018-2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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_OSPI_TEST_UTILS_H
#define MBED_OSPI_TEST_UTILS_H
#include "flash_configs/flash_configs.h"
#include "unity/unity.h"
#include "hal/ospi_api.h"
#define OSPI_NONE (-1)
enum OspiStatus {
sOK,
sError,
sTimeout,
sUnknown
};
class OspiCommand {
public:
void configure(ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width,
ospi_bus_width_t alt_width, ospi_address_size_t addr_size, ospi_alt_size_t alt_size,
int dummy_cycles = 0);
void set_dummy_cycles(int dummy_cycles);
void build(int instruction, int address = OSPI_NONE, int alt = OSPI_NONE);
ospi_command_t *get();
private:
ospi_command_t _cmd;
};
struct Ospi {
ospi_t handle;
OspiCommand cmd;
};
// MODE_Command_Address_Data_Alt
#define MODE_1_1_1 OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_SINGLE
#define MODE_1_1_2 OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_DUAL
#define MODE_1_2_2 OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_DUAL
#define MODE_2_2_2 OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_DUAL, OSPI_CFG_BUS_DUAL
#define MODE_1_1_4 OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_QUAD, OSPI_CFG_BUS_QUAD
#define MODE_1_4_4 OSPI_CFG_BUS_SINGLE, OSPI_CFG_BUS_QUAD, OSPI_CFG_BUS_QUAD, OSPI_CFG_BUS_QUAD
#define MODE_4_4_4 OSPI_CFG_BUS_QUAD, OSPI_CFG_BUS_QUAD, OSPI_CFG_BUS_QUAD, OSPI_CFG_BUS_QUAD
#define MODE_8_8_8 OSPI_CFG_BUS_OCTA, OSPI_CFG_BUS_OCTA, OSPI_CFG_BUS_OCTA, OSPI_CFG_BUS_OCTA
#define MODE_8D_8D_8D OSPI_CFG_BUS_OCTA_DTR, OSPI_CFG_BUS_OCTA_DTR, OSPI_CFG_BUS_OCTA_DTR, OSPI_CFG_BUS_OCTA_DTR
#define WRITE_1_1_1 MODE_1_1_1, OSPI_CMD_WRITE_1IO
#ifdef OSPI_CMD_WRITE_2IO
#define WRITE_1_2_2 MODE_1_2_2, OSPI_CMD_WRITE_2IO
#endif
#ifdef OSPI_CMD_WRITE_1I4O // Quad page program - command: 0x32
#define WRITE_1_1_4 MODE_1_1_4, OSPI_CMD_WRITE_1I4O
#endif
#ifdef OSPI_CMD_WRITE_4IO
#define WRITE_1_4_4 MODE_1_4_4, OSPI_CMD_WRITE_4IO
#endif
#ifdef OSPI_CMD_WRITE_DPI
#define WRITE_2_2_2 MODE_2_2_2, OSPI_CMD_WRITE_DPI
#endif
#ifdef OSPI_CMD_WRITE_QPI
#define WRITE_4_4_4 MODE_4_4_4, OSPI_CMD_WRITE_QPI
#endif
#ifdef OSPI_CMD_WRITE_OPI
#define WRITE_8_8_8 MODE_8_8_8, OSPI_CMD_WRITE_OPI
#endif
#ifdef OSPI_CMD_WRITE_OPI
#define WRITE_8D_8D_8D MODE_8D_8D_8D, OSPI_CMD_WRITE_OPI
#endif
#define READ_1_1_1 MODE_1_1_1, OSPI_CMD_READ_1IO, OSPI_READ_1IO_DUMMY_CYCLE
#ifdef OSPI_CMD_READ_1I2O
#define READ_1_1_2 MODE_1_1_2, OSPI_CMD_READ_1I2O, OSPI_READ_1I2O_DUMMY_CYCLE
#endif
#ifdef OSPI_CMD_READ_2IO
#define READ_1_2_2 MODE_1_2_2, OSPI_CMD_READ_2IO, OSPI_READ_2IO_DUMMY_CYCLE
#endif
#ifdef OSPI_CMD_READ_1I4O
#define READ_1_1_4 MODE_1_1_4, OSPI_CMD_READ_1I4O, OSPI_READ_1I4O_DUMMY_CYCLE
#endif
#ifdef OSPI_CMD_READ_4IO
#define READ_1_4_4 MODE_1_4_4, OSPI_CMD_READ_4IO, OSPI_READ_4IO_DUMMY_CYCLE
#endif
#ifdef OSPI_CMD_READ_OPI
#define READ_8_8_8 MODE_8_8_8, OSPI_CMD_READ_OPI, OSPI_READ_8IO_DUMMY_CYCLE
#endif
#ifdef OSPI_CMD_READ_DOPI
#define READ_8D_8D_8D MODE_8D_8D_8D, OSPI_CMD_READ_DOPI, OSPI_READ_8IO_DUMMY_CYCLE
#endif
#ifdef OSPI_CMD_READ_DPI
#define READ_2_2_2 MODE_2_2_2, OSPI_CMD_READ_DPI, OSPI_READ_2IO_DUMMY_CYCLE
#endif
#ifdef OSPI_CMD_READ_QPI
#define READ_4_4_4 MODE_4_4_4, OSPI_CMD_READ_QPI, OSPI_READ_4IO_DUMMY_CYCLE
#endif
#define ADDR_SIZE_8 OSPI_CFG_ADDR_SIZE_8
#define ADDR_SIZE_16 OSPI_CFG_ADDR_SIZE_16
#define ADDR_SIZE_24 OSPI_CFG_ADDR_SIZE_24
#define ADDR_SIZE_32 OSPI_CFG_ADDR_SIZE_32
#define ALT_SIZE_8 OSPI_CFG_ALT_SIZE_8
#define ALT_SIZE_16 OSPI_CFG_ALT_SIZE_16
#define ALT_SIZE_24 OSPI_CFG_ALT_SIZE_24
#define ALT_SIZE_32 OSPI_CFG_ALT_SIZE_32
#define STATUS_REG OSPI_CMD_RDSR
#define CONFIG_REG0 OSPI_CMD_RDCR0
#ifdef OSPI_CMD_RDCR1
#define CONFIG_REG1 OSPI_CMD_RDCR1
#endif
#ifdef OSPI_CMD_RDCR2
#define CONFIG_REG2 OSPI_CMD_RDCR2
#endif
#define SECURITY_REG OSPI_CMD_RDSCUR
#ifndef OSPI_CONFIG_REG_1_SIZE
#define OSPI_CONFIG_REG_1_SIZE 0
#endif
#ifndef OSPI_CONFIG_REG_2_SIZE
#define OSPI_CONFIG_REG_2_SIZE 0
#endif
#define SECTOR_ERASE OSPI_CMD_ERASE_SECTOR
#define BLOCK_ERASE OSPI_CMD_ERASE_BLOCK_64
#define SECTOR_ERASE_MAX_TIME OSPI_ERASE_SECTOR_MAX_TIME
#define BLOCK32_ERASE_MAX_TIME OSPI_ERASE_BLOCK_32_MAX_TIME
#define BLOCK64_ERASE_MAX_TIME OSPI_ERASE_BLOCK_64_MAX_TIME
#define PAGE_PROG_MAX_TIME OSPI_PAGE_PROG_MAX_TIME
#define WRSR_MAX_TIME OSPI_WRSR_MAX_TIME
#define WAIT_MAX_TIME OSPI_WAIT_MAX_TIME
ospi_status_t read_register(uint32_t cmd, uint8_t *buf, uint32_t size, Ospi &q);
ospi_status_t write_register(uint32_t cmd, uint8_t *buf, uint32_t size, Ospi &q);
OspiStatus flash_wait_for(uint32_t time_us, Ospi &ospi);
void flash_init(Ospi &ospi);
ospi_status_t write_enable(Ospi &ospi);
ospi_status_t write_disable(Ospi &ospi);
void log_register(uint32_t cmd, uint32_t reg_size, Ospi &ospi, const char *str = NULL);
ospi_status_t mode_enable(Ospi &ospi, ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width);
ospi_status_t mode_disable(Ospi &ospi, ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width);
ospi_status_t fast_mode_enable(Ospi &ospi);
ospi_status_t fast_mode_disable(Ospi &ospi);
ospi_status_t erase(uint32_t erase_cmd, uint32_t flash_addr, Ospi &ospi);
bool is_extended_mode(ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width);
bool is_dual_mode(ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width);
bool is_quad_mode(ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width);
bool is_octa_mode(ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width);
bool is_octa_dtr_mode(ospi_bus_width_t inst_width, ospi_bus_width_t addr_width, ospi_bus_width_t data_width);
#define WAIT_FOR(timeout, q) TEST_ASSERT_EQUAL_MESSAGE(sOK, flash_wait_for(timeout, q), "flash_wait_for failed!!!")
#endif // MBED_OSPI_TEST_UTILS_H

View File

@ -0,0 +1,45 @@
/* mbed Microcontroller Library
* Copyright (c) 2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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_OSPI_FLASH_MX25LM51245G_H
#define MBED_OSPI_FLASH_MX25LM51245G_H
#define OSPI_FLASH_CHIP_STRING "macronix MX25LM51245G"
// This is a workaround,
// The sfdp parameter values in Macronix old octaflash(include the MX25LM51245G on L4R9I_DISCO) are all 0xFF,
// so we need to define the parameter values by software to support SFDP parsing.
// The code below can be removed when users test with the new flash.
#define NEED_DEFINE_SFDP_PARA
#ifdef NEED_DEFINE_SFDP_PARA
uint8_t _sfdp_head_table[32] = {0x53, 0x46, 0x44, 0x50, 0x06, 0x01, 0x02, 0xFF, 0x00, 0x06, 0x01,
0x10, 0x30, 0x00, 0x00, 0xFF, 0xC2, 0x00, 0x01, 0x04, 0x10, 0x01,
0x00, 0xFF, 0x84, 0x00, 0x01, 0x02, 0xC0, 0x00, 0x00, 0xFF
};
uint8_t _sfdp_basic_param_table[64] = {0x30, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x14, 0xEC,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0x20,
0x10, 0xDC, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x50, 0xF9, 0x80
};
uint8_t _sfdp_4_byte_inst_table[8] = {0x7F, 0xEF, 0xFF, 0xFF, 0x21, 0x5C, 0xDC, 0x14};
#endif
#endif // MBED_OSPI_FLASH_MX25LM51245G_H

View File

@ -0,0 +1,454 @@
/* mbed Microcontroller Library
* Copyright (c) 2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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_OSPIF_BLOCK_DEVICE_H
#define MBED_OSPIF_BLOCK_DEVICE_H
#include "drivers/OSPI.h"
#include "drivers/internal/SFDP.h"
#include "blockdevice/BlockDevice.h"
#include "platform/Callback.h"
#ifndef MBED_CONF_OSPIF_OSPI_IO0
#define MBED_CONF_OSPIF_OSPI_IO0 NC
#endif
#ifndef MBED_CONF_OSPIF_OSPI_IO1
#define MBED_CONF_OSPIF_OSPI_IO1 NC
#endif
#ifndef MBED_CONF_OSPIF_OSPI_IO2
#define MBED_CONF_OSPIF_OSPI_IO2 NC
#endif
#ifndef MBED_CONF_OSPIF_OSPI_IO3
#define MBED_CONF_OSPIF_OSPI_IO3 NC
#endif
#ifndef MBED_CONF_OSPIF_OSPI_IO4
#define MBED_CONF_OSPIF_OSPI_IO4 NC
#endif
#ifndef MBED_CONF_OSPIF_OSPI_IO5
#define MBED_CONF_OSPIF_OSPI_IO5 NC
#endif
#ifndef MBED_CONF_OSPIF_OSPI_IO6
#define MBED_CONF_OSPIF_OSPI_IO6 NC
#endif
#ifndef MBED_CONF_OSPIF_OSPI_IO7
#define MBED_CONF_OSPIF_OSPI_IO7 NC
#endif
#ifndef MBED_CONF_OSPIF_OSPI_SCK
#define MBED_CONF_OSPIF_OSPI_SCK NC
#endif
#ifndef MBED_CONF_OSPIF_OSPI_CSN
#define MBED_CONF_OSPIF_OSPI_CSN NC
#endif
#ifndef MBED_CONF_OSPIF_OSPI_DQS
#define MBED_CONF_OSPIF_OSPI_DQS NC
#endif
#ifndef MBED_CONF_OSPIF_OSPI_POLARITY_MODE
#define MBED_CONF_OSPIF_OSPI_POLARITY_MODE 0
#endif
#ifndef MBED_CONF_OSPIF_OSPI_FREQ
#define MBED_CONF_OSPIF_OSPI_FREQ 40000000
#endif
/** Enum ospif standard error codes
*
* @enum ospif_bd_error
*/
enum ospif_bd_error {
OSPIF_BD_ERROR_OK = 0, /*!< no error */
OSPIF_BD_ERROR_DEVICE_ERROR = BD_ERROR_DEVICE_ERROR, /*!< device specific error -4001 */
OSPIF_BD_ERROR_PARSING_FAILED = -4002, /* SFDP Parsing failed */
OSPIF_BD_ERROR_READY_FAILED = -4003, /* Wait for Mem Ready failed */
OSPIF_BD_ERROR_WREN_FAILED = -4004, /* Write Enable Failed */
OSPIF_BD_ERROR_INVALID_ERASE_PARAMS = -4005, /* Erase command not on sector aligned addresses or exceeds device size */
OSPIF_BD_ERROR_DEVICE_NOT_UNIQUE = -4006, /* Only one instance per csel is allowed */
OSPIF_BD_ERROR_DEVICE_MAX_EXCEED = -4007 /* Max active OSPIF devices exceeded */
};
enum _mode {
SPI,
SOPI,
DOPI
};
/** Enum ospif polarity mode
*
* @enum ospif_polarity_mode
*/
enum ospif_polarity_mode {
OSPIF_POLARITY_MODE_0 = 0, /* CPOL=0, CPHA=0 */
OSPIF_POLARITY_MODE_1 /* CPOL=1, CPHA=1 */
};
#define OSPIF_MAX_ACTIVE_FLASH_DEVICES 10
/** BlockDevice for SFDP based flash devices over OSPI bus
*
* @code
* // Here's an example using OSPI flash device on NUCLEO_L4R9I target
* #include "mbed.h"
* #include "OSPIFBlockDevice.h"
*
* OSPIFBlockDevice block_device(OSPI_FLASH1_IO0, OSPI_FLASH1_IO1, OSPI_FLASH1_IO2, OSPI_FLASH1_IO3, OSPI_FLASH1_IO4, OSPI_FLASH1_IO5, OSPI_FLASH1_IO6, OSPI_FLASH1_IO7
* OSPI_FLASH1_SCK, OSPI_FLASH1_CSN, OSPI_FLASH1_DQS, OSPIF_POLARITY_MODE_0, MBED_CONF_OSPIF_OSPI_FREQ);
*
* int main()
* {
* printf("OSPI SFDP Flash Block Device example\n");
*
* // Initialize the OSPI flash device and print the memory layout
* block_device.init();
* bd_size_t sector_size_at_address_0 = block_device.get_erase_size(0);
*
* printf("OSPIF BD size: %llu\n", block_device.size());
* printf("OSPIF BD read size: %llu\n", block_device.get_read_size());
* printf("OSPIF BD program size: %llu\n", block_device.get_program_size());
* printf("OSPIF BD erase size (at address 0): %llu\n", sector_size_at_address_0);
*
* // Write "Hello World!" to the first block
* char *buffer = (char *) malloc(sector_size_at_address_0);
* sprintf(buffer, "Hello World!\n");
* block_device.erase(0, sector_size_at_address_0);
* block_device.program(buffer, 0, sector_size_at_address_0);
*
* // Read back what was stored
* block_device.read(buffer, 0, sector_size_at_address_0);
* printf("%s", buffer);
*
* // Deinitialize the device
* block_device.deinit();
* }
* @endcode
*/
class OSPIFBlockDevice : public mbed::BlockDevice {
public:
/** Create OSPIFBlockDevice - An SFDP based Flash Block Device over OSPI bus
*
* @param io0 1st IO pin used for sending/receiving data during data phase of a transaction
* @param io1 2nd IO pin used for sending/receiving data during data phase of a transaction
* @param io2 3rd IO pin used for sending/receiving data during data phase of a transaction
* @param io3 4th IO pin used for sending/receiving data during data phase of a transaction
* @param io4 5th IO pin used for sending/receiving data during data phase of a transaction
* @param io5 6th IO pin used for sending/receiving data during data phase of a transaction
* @param io6 7th IO pin used for sending/receiving data during data phase of a transaction
* @param io7 8th IO pin used for sending/receiving data during data phase of a transaction
* @param sclk OSPI Clock pin
* @param csel OSPI chip select pin
* @param dqs OSPI dqs pin
* @param clock_mode specifies the OSPI Clock Polarity mode (OSPIF_POLARITY_MODE_0/OSPIF_POLARITY_MODE_1)
* default value = 0
* @param freq Clock frequency of the OSPI bus (defaults to 40MHz)
*/
OSPIFBlockDevice(PinName io0 = MBED_CONF_OSPIF_OSPI_IO0,
PinName io1 = MBED_CONF_OSPIF_OSPI_IO1,
PinName io2 = MBED_CONF_OSPIF_OSPI_IO2,
PinName io3 = MBED_CONF_OSPIF_OSPI_IO3,
PinName io4 = MBED_CONF_OSPIF_OSPI_IO4,
PinName io5 = MBED_CONF_OSPIF_OSPI_IO5,
PinName io6 = MBED_CONF_OSPIF_OSPI_IO6,
PinName io7 = MBED_CONF_OSPIF_OSPI_IO7,
PinName sclk = MBED_CONF_OSPIF_OSPI_SCK,
PinName csel = MBED_CONF_OSPIF_OSPI_CSN,
PinName dqs = MBED_CONF_OSPIF_OSPI_DQS,
int clock_mode = MBED_CONF_OSPIF_OSPI_POLARITY_MODE,
int freq = MBED_CONF_OSPIF_OSPI_FREQ);
/** Initialize a block device
*
* @return OSPIF_BD_ERROR_OK(0) - success
* OSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
* OSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timedout
* OSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
*/
virtual int init();
/** Deinitialize a block device
*
* @return OSPIF_BD_ERROR_OK(0) - success
* OSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
*/
virtual int deinit();
/** Desctruct OSPIFBlockDevie
*/
~OSPIFBlockDevice()
{
deinit();
}
/** Read blocks from a block device
*
* @param buffer Buffer to write blocks to
* @param addr Address of block to begin reading from
* @param size Size to read in bytes, must be a multiple of read block size
* @return OSPIF_BD_ERROR_OK(0) - success
* OSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
*/
virtual int read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
/** Program blocks to a block device
*
* The blocks must have been erased prior to being programmed
*
* @param buffer Buffer of data to write to blocks
* @param addr Address of block to begin writing to
* @param size Size to write in bytes, must be a multiple of program block size
* @return OSPIF_BD_ERROR_OK(0) - success
* OSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
* OSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
* OSPIF_BD_ERROR_WREN_FAILED - Write Enable failed
* OSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
*/
virtual int program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
/** Erase blocks on a block device
*
* The state of an erased block is undefined until it has been programmed
*
* @param addr Address of block to begin erasing
* @param size Size to erase in bytes, must be a multiple of erase block size
* @return OSPIF_BD_ERROR_OK(0) - success
* OSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
* OSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
* OSPIF_BD_ERROR_WREN_FAILED - Write Enable failed
* OSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
* OSPIF_BD_ERROR_INVALID_ERASE_PARAMS - Trying to erase unaligned address or size
*/
virtual int erase(mbed::bd_addr_t addr, mbed::bd_size_t size);
/** Get the size of a readable block
*
* @return Size of a readable block in bytes
*/
virtual mbed::bd_size_t get_read_size() const;
/** Get the size of a programable block
*
* @return Size of a program block size in bytes
* @note Must be a multiple of the read size
*/
virtual mbed::bd_size_t get_program_size() const;
/** Get the size of a eraseable block
*
* @return Size of a minimal erase block, common to all regions, in bytes
* @note Must be a multiple of the program size
*/
virtual mbed::bd_size_t get_erase_size() const;
/** Get the size of minimal eraseable sector size of given address
*
* @param addr Any address within block queried for erase sector size (can be any address within flash size offset)
* @return Size of minimal erase sector size, in given address region, in bytes
* @note Must be a multiple of the program size
*/
virtual mbed::bd_size_t get_erase_size(mbed::bd_addr_t addr);
/** Get the value of storage byte after it was erased
*
* If get_erase_value returns a non-negative byte value, the underlying
* storage is set to that value when erased, and storage containing
* that value can be programmed without another erase.
*
* @return The value of storage when erased, or -1 if you can't
* rely on the value of erased storage
*/
virtual int get_erase_value() const;
/** Get the total size of the underlying device
*
* @return Size of the underlying device in bytes
*/
virtual mbed::bd_size_t size() const;
/** Get the BlockDevice class type.
*
* @return A string represent the BlockDevice class type.
*/
virtual const char *get_type() const;
/** Change the operation mode(SPI, SOPI or DOPI) of flash.
*
* @return OSPIF_BD_ERROR_OK(0) - success
* OSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
* OSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
* OSPIF_BD_ERROR_WREN_FAILED - Write Enable failed
* OSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
* OSPIF_BD_ERROR_INVALID_ERASE_PARAMS - Trying to erase unaligned address or size
*/
virtual int change_mode(int mode);
private:
/********************************/
/* Different Device Csel Mgmt */
/********************************/
// Add a new OSPI device CS to existing devices list.
// Only one OSPIFBlockDevice instance per CS is allowed
int add_new_csel_instance(PinName csel);
// Remove device CS from existing device list upon destroying object (last deinit is called)
int remove_csel_instance(PinName csel);
/********************************/
/* Calls to OSPI Driver APIs */
/********************************/
// Send Program/Write command to Driver
ospi_status_t _ospi_send_program_command(mbed::ospi_inst_t prog_instruction, const void *buffer,
mbed::bd_addr_t addr, mbed::bd_size_t *size);
// Send Read command to Driver
ospi_status_t _ospi_send_read_command(mbed::ospi_inst_t read_instruction, void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
// Send Erase Instruction using command_transfer command to Driver
ospi_status_t _ospi_send_erase_command(mbed::ospi_inst_t erase_instruction, mbed::bd_addr_t addr, mbed::bd_size_t size);
// Send Generic command_transfer command to Driver
ospi_status_t _ospi_send_general_command(mbed::ospi_inst_t instruction_int, mbed::bd_addr_t addr, const char *tx_buffer,
mbed::bd_size_t tx_length, const char *rx_buffer, mbed::bd_size_t rx_length);
// Send command to read from the SFDP table
int _ospi_send_read_sfdp_command(mbed::bd_addr_t addr, void *rx_buffer, mbed::bd_size_t rx_length);
// Read the contents of status registers 1 and 2 into a buffer (buffer must have a length of 2)
ospi_status_t _ospi_read_status_registers(uint8_t *reg_buffer);
// Set the contents of status registers 1 and 2 from a buffer (buffer must have a length of 2)
ospi_status_t _ospi_write_status_registers(uint8_t *reg_buffer);
// Send set_frequency command to Driver
ospi_status_t _ospi_set_frequency(int freq);
// Update the 4-byte addressing extension register with the MSB of the address if it is in use
ospi_status_t _ospi_update_4byte_ext_addr_reg(bd_addr_t addr);
/*********************************/
/* Flash Configuration Functions */
/*********************************/
// Clear the device's block protection
int _clear_block_protection();
// Configure Write Enable in Status Register
int _set_write_enable();
// Wait on status register until write not-in-progress
bool _is_mem_ready();
// Enable Fast Mode - for flash chips with low power default
int _enable_fast_mode();
// Enable OPI Mode
int _enable_opi_mdoe();
// Query vendor ID and handle special behavior that isn't covered by SFDP data
int _handle_vendor_quirks();
/****************************************/
/* SFDP Detection and Parsing Functions */
/****************************************/
// Parse and Detect required Basic Parameters from Table
int _sfdp_parse_basic_param_table(mbed::Callback<int(mbed::bd_addr_t, void *, mbed::bd_size_t)> sfdp_reader,
mbed::sfdp_hdr_info &sfdp_info);
// Parse and Detect 4-Byte Address Instruction Parameters from Table
int _sfdp_parse_4_byte_inst_table(mbed::Callback<int(mbed::bd_addr_t, void *, mbed::bd_size_t)> sfdp_reader,
mbed::sfdp_hdr_info &sfdp_info);
// Detect the soft reset protocol and reset - returns error if soft reset is not supported
int _sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param_table_ptr);
// Detect fastest read Bus mode supported by device
int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size,
bool &set_quad_enable, bool &is_qpi_mode, bool &is_opi_mode);
// Enable Quad mode if supported (1-1-4, 1-4-4, 4-4-4 bus modes)
int _sfdp_set_quad_enabled(uint8_t *basic_param_table_ptr);
// Enable QPI mode (4-4-4)
int _sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr);
// Detect 4-byte addressing mode and enable it if supported
int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size);
private:
enum ospif_clear_protection_method_t {
OSPIF_BP_ULBPR, // Issue global protection unlock instruction
OSPIF_BP_CLEAR_SR, // Clear protection bits in status register 1
};
// OSPI Driver Object
mbed::OSPI _ospi;
// Static List of different OSPI based Flash devices csel that already exist
// Each OSPI Flash device csel can have only 1 OSPIFBlockDevice instance
// _devices_mutex is used to lock csel list - only one OSPIFBlockDevice instance per csel is allowed
static SingletonPtr<PlatformMutex> _devices_mutex;
static int _number_of_active_ospif_flash_csel;
static PinName *_active_ospif_flash_csel_arr;
int _unique_device_status;
PinName _csel;
// Mutex is used to protect Flash device for some OSPI Driver commands that must be done sequentially with no other commands in between
// e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
PlatformMutex _mutex;
// Command Instructions
mbed::ospi_inst_t _read_instruction;
mbed::ospi_inst_t _prog_instruction;
mbed::ospi_inst_t _legacy_erase_instruction;
// Status register write/read instructions
unsigned int _num_status_registers;
mbed::ospi_inst_t _write_status_reg_2_inst;
mbed::ospi_inst_t _read_status_reg_2_inst; // If three registers, this instruction reads the latter two
// Attempt to enable 4-byte addressing. True by default, but may be disabled for some vendors
bool _attempt_4_byte_addressing;
// 4-byte addressing extension register write instruction
mbed::ospi_inst_t _4byte_msb_reg_write_inst;
// Flash support 4-Byte instructions,like READ4B(0x13).
bool _support_4_byte_inst;
// Quad mode enable status register and bit
int _quad_enable_register_idx;
int _quad_enable_bit;
bool _needs_fast_mode;
// Clear block protection
ospif_clear_protection_method_t _clear_protection_method;
// Data extracted from the devices SFDP structure
mbed::sfdp_hdr_info _sfdp_info;
unsigned int _page_size_bytes; // Page size - 256 Bytes default
int _freq;
// Bus speed configuration
ospi_bus_width_t _inst_width; //Bus width for Instruction phase
ospi_inst_size_t _inst_size; //Instruction Size
ospi_bus_width_t _address_width; //Bus width for Address phase
ospi_address_size_t _address_size; //Number of bits for address
ospi_alt_size_t _alt_size; //Number of bits for alt
bool _alt_enabled; //Whether alt is enabled
uint8_t _dummy_cycles; //Number of Dummy cycles required by Current Bus Mode
ospi_bus_width_t _data_width; //Bus width for Data phase
uint32_t _init_ref_count;
bool _is_initialized;
};
#endif

View File

@ -0,0 +1,33 @@
{
"name": "ospif",
"config": {
"enable-and-reset": {
"help": "(Legacy SFDP 1.0 ONLY) Reset sequence is enable reset (0x66) then reset (0x99)",
"value": false
},
"direct-reset": {
"help": "(Legacy SFDP 1.0 ONLY) Reset involves a single command (0xF0)",
"value": false
},
"OSPI_IO0": "MBED_CONF_DRIVERS_OSPI_IO0",
"OSPI_IO1": "MBED_CONF_DRIVERS_OSPI_IO1",
"OSPI_IO2": "MBED_CONF_DRIVERS_OSPI_IO2",
"OSPI_IO3": "MBED_CONF_DRIVERS_OSPI_IO3",
"OSPI_IO4": "MBED_CONF_DRIVERS_OSPI_IO4",
"OSPI_IO5": "MBED_CONF_DRIVERS_OSPI_IO5",
"OSPI_IO6": "MBED_CONF_DRIVERS_OSPI_IO6",
"OSPI_IO7": "MBED_CONF_DRIVERS_OSPI_IO7",
"OSPI_SCK": "MBED_CONF_DRIVERS_OSPI_SCK",
"OSPI_CSN": "MBED_CONF_DRIVERS_OSPI_CSN",
"OSPI_DQS": "MBED_CONF_DRIVERS_OSPI_DQS",
"OSPI_POLARITY_MODE": 0,
"OSPI_FREQ": "40000000",
"OSPI_MIN_READ_SIZE": "1",
"OSPI_MIN_PROG_SIZE": "256"
},
"target_overrides": {
"MX25LM51245G": {
"OSPI_FREQ": "66000000"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,10 @@
#include "QSPIFBlockDevice.h"
#endif
#if COMPONENT_OSPIF
#include "OSPIFBlockDevice.h"
#endif
#if COMPONENT_DATAFLASH
#include "DataFlashBlockDevice.h"
#endif
@ -86,10 +90,11 @@ enum bd_type {
dataflash,
sd,
flashiap,
ospif,
default_bd
};
uint8_t bd_arr[5] = {0};
uint8_t bd_arr[6] = {0};
static uint8_t test_iteration = 0;
@ -133,6 +138,27 @@ static BlockDevice *get_bd_instance(uint8_t bd_type)
MBED_CONF_QSPIF_QSPI_FREQ
);
return &default_bd;
#endif
break;
}
case ospif: {
#if COMPONENT_OSPIF
static OSPIFBlockDevice default_bd(
MBED_CONF_OSPIF_OSPI_IO0,
MBED_CONF_OSPIF_OSPI_IO1,
MBED_CONF_OSPIF_OSPI_IO2,
MBED_CONF_OSPIF_OSPI_IO3,
MBED_CONF_OSPIF_OSPI_IO4,
MBED_CONF_OSPIF_OSPI_IO5,
MBED_CONF_OSPIF_OSPI_IO6,
MBED_CONF_OSPIF_OSPI_IO7,
MBED_CONF_OSPIF_OSPI_SCK,
MBED_CONF_OSPIF_OSPI_CSN,
MBED_CONF_OSPIF_OSPI_DQS,
MBED_CONF_OSPIF_OSPI_POLARITY_MODE,
MBED_CONF_OSPIF_OSPI_FREQ
);
return &default_bd;
#endif
break;
}
@ -746,13 +772,15 @@ void test_get_type_functionality()
#if COMPONENT_QSPIF
TEST_ASSERT_EQUAL(0, strcmp(bd_type, "QSPIF"));
#elif COMPONENT_OSPIF
TEST_ASSERT_EQUAL(0, strcmp(bd_type, "OSPIF"));
#elif COMPONENT_SPIF
TEST_ASSERT_EQUAL(0, strcmp(bd_type, "SPIF"));
#elif COMPONENT_DATAFLASH
TEST_ASSERT_EQUAL(0, strcmp(bd_type, "DATAFLASH"));
#elif COMPONENT_SD
TEST_ASSERT_EQUAL(0, strcmp(bd_type, "SD"));
#elif COMPONET_FLASHIAP
#elif COMPONENT_FLASHIAP
TEST_ASSERT_EQUAL(0, strcmp(bd_type, "FLASHIAP"));
#endif
}
@ -809,11 +837,14 @@ int get_bd_count()
#if COMPONENT_FLASHIAP
bd_arr[count++] = flashiap; //4
#endif
#if COMPONENT_OSPIF
bd_arr[count++] = ospif; //5
#endif
return count;
}
static const char *prefix[] = {"SPIF ", "QSPIF ", "DATAFLASH ", "SD ", "FLASHIAP ", "DEFAULT "};
static const char *prefix[] = {"SPIF ", "QSPIF ", "DATAFLASH ", "SD ", "FLASHIAP ", "OSPIF ", "DEFAULT "};
int main()
{

View File

@ -43,6 +43,10 @@
#include "SPIFBlockDevice.h"
#endif
#if COMPONENT_OSPIF
#include "OSPIFBlockDevice.h"
#endif
#if COMPONENT_DATAFLASH
#include "DataFlashBlockDevice.h"
#endif
@ -79,7 +83,7 @@ int _storage_config_TDB_INTERNAL();
* MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_SIZE - Size of the external blockdevice in bytes or NULL for
* max possible size.
* MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_BASE_ADDRESS - The block device start address.
* MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_BLOCK_DEVICE - Alowed vlaues are: default, SPIF, DATAFASH, QSPIF or SD
* MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_BLOCK_DEVICE - Alowed vlaues are: default, SPIF, DATAFASH, QSPIF, OSPIF or SD
* @returns 0 on success or negative value on failure.
*/
int _storage_config_TDB_EXTERNAL();
@ -92,7 +96,7 @@ int _storage_config_TDB_EXTERNAL();
* MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_EXTERNAL_SIZE - Size of the external blockdevice in bytes
* or NULL for max possible size.
* MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_EXTERNAL_BASE_ADDRESS - The block device start address
* MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_EXTERNAL_BLOCK_DEVICE - Alowed vlaues are: default, SPIF, DATAFASH, QSPIF or SD
* MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_EXTERNAL_BLOCK_DEVICE - Alowed vlaues are: default, SPIF, DATAFASH, QSPIF, OSPIF or SD
* @returns 0 on success or negative value on failure.
*/
int _storage_config_TDB_EXTERNAL_NO_RBP();
@ -109,7 +113,7 @@ int _storage_config_TDB_EXTERNAL_NO_RBP();
* flash - rbp_internal_size.
* MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS - The satrt address of the internal FlashIAPBlockDevice.
* MBED_CONF_STORAGE_FILESYSTEM_FILESYSTEM - Allowed values are: default, FAT or LITTLE
* MBED_CONF_STORAGE_FILESYSTEM_BLOCKDEVICE - Allowed values are: default, SPIF, DATAFASH, QSPIF or SD
* MBED_CONF_STORAGE_FILESYSTEM_BLOCKDEVICE - Allowed values are: default, SPIF, DATAFASH, QSPIF, OSPIF or SD
* MBED_CONF_STORAGE_FILESYSTEM_EXTERNAL_SIZE - External Blockdevice size in bytes or NULL for max possible size.
* MBED_CONF_STORAGE_FILESYSTEM_EXTERNAL_BASE_ADDRESS - The block device start address.
* MBED_CONF_STORAGE_FILESYSTEM_MOUNT_POINT - Where to mount the filesystem
@ -125,7 +129,7 @@ int _storage_config_FILESYSTEM();
* filesystem with default blockdevice unless differently configured.
* The following is a list of configuration parameter:
* MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_FILESYSTEM - Allowed values are: default, FAT or LITTLE
* MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_BLOCKDEVICE - Allowed values are: default, SPIF, DATAFASH, QSPIF or SD
* MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_BLOCKDEVICE - Allowed values are: default, SPIF, DATAFASH, QSPIF, OSPIF or SD
* MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_EXTERNAL_SIZE - Blockdevice size in bytes. or NULL for max possible size.
* MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_EXTERNAL_BASE_ADDRESS - The block device start address.
* MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_MOUNT_POINT - Where to mount the filesystem
@ -256,7 +260,7 @@ FileSystemStore *_get_file_system_store(FileSystem *fs)
FileSystem *_get_filesystem_default(const char *mount)
{
#if COMPONENT_QSPIF || COMPONENT_SPIF || COMPONENT_DATAFLASH
#if COMPONENT_QSPIF || COMPONENT_SPIF || COMPONENT_DATAFLASH || COMPONENT_OSPIF
return _get_filesystem_LITTLE(mount);
#elif COMPONENT_SD
return _get_filesystem_FAT(mount);
@ -375,6 +379,55 @@ BlockDevice *_get_blockdevice_QSPIF(bd_addr_t start_address, bd_size_t size)
#endif
}
BlockDevice *_get_blockdevice_OSPIF(bd_addr_t start_address, bd_size_t size)
{
#if COMPONENT_OSPIF
bd_addr_t aligned_end_address;
bd_addr_t aligned_start_address;
static OSPIFBlockDevice bd(
MBED_CONF_OSPIF_OSPI_IO0,
MBED_CONF_OSPIF_OSPI_IO1,
MBED_CONF_OSPIF_OSPI_IO2,
MBED_CONF_OSPIF_OSPI_IO3,
MBED_CONF_OSPIF_OSPI_IO4,
MBED_CONF_OSPIF_OSPI_IO5,
MBED_CONF_OSPIF_OSPI_IO6,
MBED_CONF_OSPIF_OSPI_IO7,
MBED_CONF_OSPIF_OSPI_SCK,
MBED_CONF_OSPIF_OSPI_CSN,
MBED_CONF_OSPIF_OSPI_DQS,
MBED_CONF_OSPIF_OSPI_POLARITY_MODE,
MBED_CONF_OSPIF_OSPI_FREQ
);
if (bd.init() != MBED_SUCCESS) {
tr_error("KV Config: OSPIFBlockDevice init fail");
return NULL;
}
if (start_address == 0 && size == 0) {
return &bd;
}
//If address and size were specified use SlicingBlockDevice to get the correct block device size and start address.
if (_get_addresses(&bd, start_address, size, &aligned_start_address, &aligned_end_address) != 0) {
tr_error("KV Config: Fail to get addresses for SlicingBlockDevice.");
return NULL;
}
start_address = aligned_start_address;
size = aligned_end_address - aligned_start_address;
static SlicingBlockDevice sbd(&bd, aligned_start_address, aligned_end_address);
return &sbd;
#else
return NULL;
#endif
}
BlockDevice *_get_blockdevice_DATAFLASH(bd_addr_t start_address, bd_size_t size)
{
#if COMPONENT_DATAFLASH
@ -491,6 +544,8 @@ BlockDevice *_get_blockdevice_default(bd_addr_t start_address, bd_size_t size)
return _get_blockdevice_QSPIF(start_address, size);
#elif COMPONENT_SPIF
return _get_blockdevice_SPIF(start_address, size);
#elif COMPONENT_OSPIF
return _get_blockdevice_OSPIF(start_address, size);
#elif COMPONENT_DATAFLASH
return _get_blockdevice_DATAFLASH(start_address, size);
#elif COMPONENT_SD

View File

@ -28,6 +28,10 @@
#include "QSPIFBlockDevice.h"
#endif
#if COMPONENT_OSPIF
#include "OSPIFBlockDevice.h"
#endif
#if COMPONENT_DATAFLASH
#include "DataFlashBlockDevice.h"
#endif
@ -75,6 +79,12 @@ MBED_WEAK BlockDevice *BlockDevice::get_default_instance()
return &default_bd;
#elif COMPONENT_OSPIF
static OSPIFBlockDevice default_bd;
return &default_bd;
#elif COMPONENT_DATAFLASH
static DataFlashBlockDevice default_bd;
@ -140,7 +150,7 @@ MBED_WEAK BlockDevice *BlockDevice::get_default_instance()
MBED_WEAK FileSystem *FileSystem::get_default_instance()
{
#if COMPONENT_SPIF || COMPONENT_QSPIF || COMPONENT_DATAFLASH
#if COMPONENT_SPIF || COMPONENT_QSPIF || COMPONENT_OSPIF || COMPONENT_DATAFLASH
static LittleFileSystem flash("flash", BlockDevice::get_default_instance());
flash.set_as_default();

View File

@ -90,6 +90,21 @@ extern const PinMap PinMap_QSPI_SCLK[];
extern const PinMap PinMap_QSPI_SSEL[];
#endif
//*** OSPI ***
#if DEVICE_OSPI
extern const PinMap PinMap_OSPI_DATA0[];
extern const PinMap PinMap_OSPI_DATA1[];
extern const PinMap PinMap_OSPI_DATA2[];
extern const PinMap PinMap_OSPI_DATA3[];
extern const PinMap PinMap_OSPI_DATA4[];
extern const PinMap PinMap_OSPI_DATA5[];
extern const PinMap PinMap_OSPI_DATA6[];
extern const PinMap PinMap_OSPI_DATA7[];
extern const PinMap PinMap_OSPI_DQS[];
extern const PinMap PinMap_OSPI_SCLK[];
extern const PinMap PinMap_OSPI_SSEL[];
#endif
//*** USB ***
#define USE_USB_NO_OTG 0
#define USE_USB_OTG_FS 1

View File

@ -88,6 +88,11 @@ typedef enum {
QSPI_2 = (int)OCTOSPI2_R_BASE
} QSPIName;
typedef enum {
OSPI_1 = (int)OCTOSPI1_R_BASE,
OSPI_2 = (int)OCTOSPI2_R_BASE
} OSPIName;
typedef enum {
USB_FS = (int)USB_OTG_FS_PERIPH_BASE,
} USBName;

View File

@ -447,6 +447,87 @@ MBED_WEAK const PinMap PinMap_QSPI_SSEL[] = {
{NC, NC, 0}
};
//*** OCTOSPI ***
MBED_WEAK const PinMap PinMap_OSPI_DATA0[] = {
{PB_1, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_IO0
{PE_12, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_IO0 // Connected to D9
{PF_0, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_IO0 // Connected to PSRAM_A0
{PI_11, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_IO0 // Connected to OCTOSPIM_P2_IO0
{NC, NC, 0}
};
MBED_WEAK const PinMap PinMap_OSPI_DATA1[] = {
{PB_0, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_IO1 // Connected to ARD_A3
{PE_13, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_IO1 // Connected to D10
{PF_1, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_IO1 // Connected to PSRAM_A1
{PI_10, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_IO1 // Connected to OCTOSPIM_P2_IO1
{NC, NC, 0}
};
MBED_WEAK const PinMap PinMap_OSPI_DATA2[] = {
{PA_7, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_IO2 // Connected to ARD_A0
{PE_14, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_IO2 // Connected to D11
{PF_2, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_IO2 // Connected to PSRAM_A2
{PI_9, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_IO2 // Connected to OCTOSPIM_P2_IO2
{NC, NC, 0}
};
MBED_WEAK const PinMap PinMap_OSPI_DATA3[] = {
{PA_6, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_IO3 // Connected to SPI2_CS
{PE_15, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_IO3 // Connected to D12
{PF_3, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_IO3 // Connected to PSRAM_A3
{PH_8, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_IO3 // Connected to OCTOSPI_P2_IO3
{NC, NC, 0}
};
MBED_WEAK const PinMap PinMap_OSPI_DATA4[] = {
{PH_9, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_IO4 // Connected to OCTOSPI_P2_IO4
{NC, NC, 0}
};
MBED_WEAK const PinMap PinMap_OSPI_DATA5[] = {
{PH_10, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_IO5 // Connected to OCTOSPI_P2_IO5
{NC, NC, 0}
};
MBED_WEAK const PinMap PinMap_OSPI_DATA6[] = {
{PG_9, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_IO6 // Connected to OCTOSPI_P2_IO6
{NC, NC, 0}
};
MBED_WEAK const PinMap PinMap_OSPI_DATA7[] = {
{PG_10, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_IO7 // Connected to OCTOSPI_P2_IO7
{NC, NC, 0}
};
MBED_WEAK const PinMap PinMap_OSPI_DQS[] = {
{PG_15, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_DQS // Connected to OCTOSPI_P2_DQS
{NC, NC, 0}
};
MBED_WEAK const PinMap PinMap_OSPI_SCLK[] = {
// {PA_3, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_CLK // Connected to STDIO_UART_RX
{PB_10, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_CLK // Connected to USART3_TX
{PE_10, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_CLK // Connected to D7
{PF_4, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_CLK // Connected to PSRAM_A4
{PF_10, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_OCTOSPIM_P1)}, // OCTOSPIM_P1_CLK
{PI_6, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_CLK // Connected to OCTOSPIM_P2_CLK
{NC, NC, 0}
};
MBED_WEAK const PinMap PinMap_OSPI_SSEL[] = {
// {PA_2, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_NCS // Connected to STDIO_UART_TX
{PA_4, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_OCTOSPIM_P1)}, // OCTOSPIM_P1_NCS // Connected to DCMI_HSYNC
{PB_11, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_NCS // Connected to USART3_RX
{PC_11, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P1)}, // OCTOSPIM_P1_NCS // Connected to uSD_D3
{PD_3, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P2)}, // OCTOSPIM_P2_NCS // Connected to PSRAM_CLK
{PE_11, OSPI_1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_OCTOSPIM_P1)}, // OCTOSPIM_P1_NCS // Connected to D8
{PG_12, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_NCS // Connected to OCTOSPIM_P2_CS
{PI_5, OSPI_2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_OCTOSPIM_P2)}, // OCTOSPIM_P2_NCS // Connected to DCMI_VSYNC
{NC, NC, 0}
};
//*** USBDEVICE ***
MBED_WEAK const PinMap PinMap_USB_FS[] = {

View File

@ -358,6 +358,19 @@ typedef enum {
QSPI_FLASH1_SCK = PI_6,
QSPI_FLASH1_CSN = PG_12,
/**** OSPI FLASH pins ****/
OSPI_FLASH1_IO0 = PI_11,
OSPI_FLASH1_IO1 = PI_10,
OSPI_FLASH1_IO2 = PI_9,
OSPI_FLASH1_IO3 = PH_8,
OSPI_FLASH1_IO4 = PH_9,
OSPI_FLASH1_IO5 = PH_10,
OSPI_FLASH1_IO6 = PG_9,
OSPI_FLASH1_IO7 = PG_10,
OSPI_FLASH1_DQS = PG_15,
OSPI_FLASH1_SCK = PI_6,
OSPI_FLASH1_CSN = PG_12,
/**** STMOD+ pins ****/
STMOD_1 = PA_6,
STMOD_2 = PB_10,

View File

@ -168,6 +168,24 @@ struct qspi_s {
};
#endif
#if DEVICE_OSPI
struct ospi_s {
OSPI_HandleTypeDef handle;
OSPIName ospi;
PinName io0;
PinName io1;
PinName io2;
PinName io3;
PinName io4;
PinName io5;
PinName io6;
PinName io7;
PinName sclk;
PinName ssel;
PinName dqs;
};
#endif
#define HAL_CRC_IS_SUPPORTED(polynomial, width) ((width) == 7 || (width) == 8 || (width) == 16 || (width) == 32)
#endif

View File

@ -0,0 +1,625 @@
/*
* Copyright (c) 2020, Arm Limited and affiliates.
* Copyright (c) 2020, STMicroelectronics.
* SPDX-License-Identifier: Apache-2.0
*
* 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_OSPI
#include "ospi_api.h"
#include "mbed_error.h"
#include "mbed_debug.h"
#include "cmsis.h"
#include "pinmap.h"
#include "PeripheralPins.h"
#include "mbed-trace/mbed_trace.h"
#define TRACE_GROUP "STOS"
// activate / de-activate debug
#define ospi_api_c_debug 0
/* Max amount of flash size is 4Gbytes */
/* hence 2^(31+1), then FLASH_SIZE_DEFAULT = 1<<31 */
#define OSPI_FLASH_SIZE_DEFAULT 0x80000000
static uint32_t get_alt_bytes_size(const uint32_t num_bytes)
{
switch (num_bytes) {
case 1:
return HAL_OSPI_ALTERNATE_BYTES_8_BITS;
case 2:
return HAL_OSPI_ALTERNATE_BYTES_16_BITS;
case 3:
return HAL_OSPI_ALTERNATE_BYTES_24_BITS;
case 4:
return HAL_OSPI_ALTERNATE_BYTES_32_BITS;
}
error("Invalid alt bytes size");
return 0xFFFFFFFF;
}
ospi_status_t ospi_prepare_command(const ospi_command_t *command, OSPI_RegularCmdTypeDef *st_command)
{
debug_if(ospi_api_c_debug, "ospi_prepare_command In: instruction.value %x dummy_count %x address.bus_width %x address.disabled %x address.value %x address.size %x\n",
command->instruction.value, command->dummy_count, command->address.bus_width, command->address.disabled, command->address.value, command->address.size);
st_command->FlashId = HAL_OSPI_FLASH_ID_1;
if (command->instruction.disabled == true) {
st_command->InstructionMode = HAL_OSPI_INSTRUCTION_NONE;
st_command->Instruction = 0;
} else {
st_command->Instruction = ((command->instruction.bus_width == OSPI_CFG_BUS_OCTA) || (command->instruction.bus_width == OSPI_CFG_BUS_OCTA_DTR))
? command->instruction.value << 8 | (0xFF - command->instruction.value) : command->instruction.value;
switch (command->instruction.bus_width) {
case OSPI_CFG_BUS_SINGLE:
st_command->InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
break;
case OSPI_CFG_BUS_DUAL:
st_command->InstructionMode = HAL_OSPI_INSTRUCTION_2_LINES;
break;
case OSPI_CFG_BUS_QUAD:
st_command->InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES;
break;
case OSPI_CFG_BUS_OCTA:
case OSPI_CFG_BUS_OCTA_DTR:
st_command->InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;
break;
default:
error("Command param error: wrong instruction format\n");
return OSPI_STATUS_ERROR;
}
}
st_command->InstructionSize = (st_command->InstructionMode == HAL_OSPI_INSTRUCTION_8_LINES) ? HAL_OSPI_INSTRUCTION_16_BITS : HAL_OSPI_INSTRUCTION_8_BITS;
st_command->InstructionDtrMode = (command->instruction.bus_width == OSPI_CFG_BUS_OCTA_DTR) ? HAL_OSPI_INSTRUCTION_DTR_ENABLE :HAL_OSPI_INSTRUCTION_DTR_DISABLE;
st_command->DummyCycles = command->dummy_count;
// these are target specific settings, use default values
st_command->SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
st_command->DataDtrMode = (command->instruction.bus_width == OSPI_CFG_BUS_OCTA_DTR) ? HAL_OSPI_DATA_DTR_ENABLE : HAL_OSPI_DATA_DTR_DISABLE;
st_command->AddressDtrMode = (command->instruction.bus_width == OSPI_CFG_BUS_OCTA_DTR) ? HAL_OSPI_ADDRESS_DTR_ENABLE : HAL_OSPI_ADDRESS_DTR_DISABLE;
st_command->AlternateBytesDtrMode = (command->instruction.bus_width == OSPI_CFG_BUS_OCTA_DTR) ? HAL_OSPI_ALTERNATE_BYTES_DTR_ENABLE : HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE;
st_command->DQSMode = (command->instruction.bus_width == OSPI_CFG_BUS_OCTA_DTR) ? HAL_OSPI_DQS_ENABLE :HAL_OSPI_DQS_DISABLE;
st_command->OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
if (command->address.disabled == true) {
st_command->AddressMode = HAL_OSPI_ADDRESS_NONE;
st_command->AddressSize = 0;
} else {
st_command->Address = command->address.value;
switch (command->address.bus_width) {
case OSPI_CFG_BUS_SINGLE:
st_command->AddressMode = HAL_OSPI_ADDRESS_1_LINE;
break;
case OSPI_CFG_BUS_DUAL:
st_command->AddressMode = HAL_OSPI_ADDRESS_2_LINES;
break;
case OSPI_CFG_BUS_QUAD:
st_command->AddressMode = HAL_OSPI_ADDRESS_4_LINES;
break;
case OSPI_CFG_BUS_OCTA:
case OSPI_CFG_BUS_OCTA_DTR:
st_command->AddressMode = HAL_OSPI_ADDRESS_8_LINES;
break;
default:
error("Command param error: wrong address size\n");
return OSPI_STATUS_ERROR;
}
switch (command->address.size) {
case OSPI_CFG_ADDR_SIZE_8:
st_command->AddressSize = HAL_OSPI_ADDRESS_8_BITS;
break;
case OSPI_CFG_ADDR_SIZE_16:
st_command->AddressSize = HAL_OSPI_ADDRESS_16_BITS;
break;
case OSPI_CFG_ADDR_SIZE_24:
st_command->AddressSize = HAL_OSPI_ADDRESS_24_BITS;
break;
case OSPI_CFG_ADDR_SIZE_32:
st_command->AddressSize = HAL_OSPI_ADDRESS_32_BITS;
break;
default:
error("Command param error: wrong address size\n");
return OSPI_STATUS_ERROR;
}
}
if (command->alt.disabled == true) {
st_command->AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
st_command->AlternateBytesSize = 0;
} else {
uint8_t alt_lines = 0;
switch (command->alt.bus_width) {
case OSPI_CFG_BUS_SINGLE:
st_command->AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_1_LINE;
alt_lines = 1;
break;
case OSPI_CFG_BUS_DUAL:
st_command->AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_2_LINES;
alt_lines = 2;
break;
case OSPI_CFG_BUS_QUAD:
st_command->AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_4_LINES;
alt_lines = 4;
break;
case OSPI_CFG_BUS_OCTA:
case OSPI_CFG_BUS_OCTA_DTR:
st_command->AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_8_LINES;
alt_lines = 8;
break;
default:
st_command->AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
error("Command param error: invalid alt bytes mode\n");
return OSPI_STATUS_ERROR;
}
// Alt size must be a multiple of the number of bus lines used (i.e. a whole number of cycles)
if (command->alt.size % alt_lines != 0) {
error("Command param error: incompatible alt size and alt bus width\n");
return OSPI_STATUS_ERROR;
}
// Round up to nearest byte - unused parts of byte act as dummy cycles
uint32_t alt_bytes = ((command->alt.size - 1) >> 3) + 1;
// Maximum of 4 alt bytes
if (alt_bytes > 4) {
error("Command param error: alt size exceeds maximum of 32 bits\n");
return OSPI_STATUS_ERROR;
}
// Unused bits in most significant byte of alt
uint8_t leftover_bits = (alt_bytes << 3) - command->alt.size;
if (leftover_bits != 0) {
// Account for dummy cycles that will be spent in the alt portion of the command
uint8_t integrated_dummy_cycles = leftover_bits / alt_lines;
if (st_command->DummyCycles < integrated_dummy_cycles) {
// Not enough dummy cycles to account for a short alt
error("Command param error: not enough dummy cycles to make up for given alt size\n");
return OSPI_STATUS_ERROR;
}
st_command->DummyCycles -= integrated_dummy_cycles;
// Align alt value to the end of the most significant byte
st_command->AlternateBytes = command->alt.value << leftover_bits;
} else {
st_command->AlternateBytes = command->alt.value;
}
st_command->AlternateBytesSize = get_alt_bytes_size(alt_bytes);
}
switch (command->data.bus_width) {
case OSPI_CFG_BUS_SINGLE:
st_command->DataMode = HAL_OSPI_DATA_1_LINE;
break;
case OSPI_CFG_BUS_DUAL:
st_command->DataMode = HAL_OSPI_DATA_2_LINES;
break;
case OSPI_CFG_BUS_QUAD:
st_command->DataMode = HAL_OSPI_DATA_4_LINES;
break;
case OSPI_CFG_BUS_OCTA:
case OSPI_CFG_BUS_OCTA_DTR:
st_command->DataMode = HAL_OSPI_DATA_8_LINES;
break;
default:
st_command->DataMode = HAL_OSPI_DATA_NONE;
break;
}
debug_if(ospi_api_c_debug, "ospi_prepare_command Out: InstructionMode %x Instruction %x AddressMode %x AddressSize %x Address %x DataMode %x\n",
st_command->InstructionMode, st_command->Instruction, st_command->AddressMode, st_command->AddressSize, st_command->Address, st_command->DataMode);
return OSPI_STATUS_OK;
}
#if STATIC_PINMAP_READY
#define OSPI_INIT_DIRECT ospi_init_direct
ospi_status_t ospi_init_direct(ospi_t *obj, const ospi_pinmap_t *pinmap, uint32_t hz, uint8_t mode)
#else
#define OSPI_INIT_DIRECT _ospi_init_direct
static ospi_status_t _ospi_init_direct(ospi_t *obj, const ospi_pinmap_t *pinmap, uint32_t hz, uint8_t mode)
#endif
{
tr_info("ospi_init mode %u", mode);
// Reset handle internal state
obj->handle.State = HAL_OSPI_STATE_RESET;
// Set default OCTOSPI handle values
obj->handle.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
//#if defined(TARGET_MX25LM512451G)
// obj->handle.Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX; // Read sequence in DTR mode: D1-D0-D3-D2
//#else
obj->handle.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON; // Read sequence in DTR mode: D0-D1-D2-D3
//#endif
obj->handle.Init.ClockPrescaler = 4; // default value, will be overwritten in ospi_frequency
obj->handle.Init.FifoThreshold = 4;
obj->handle.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
obj->handle.Init.DeviceSize = POSITION_VAL(OSPI_FLASH_SIZE_DEFAULT) - 1;
obj->handle.Init.ChipSelectHighTime = 3;
obj->handle.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
obj->handle.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
obj->handle.Init.ClockMode = mode == 0 ? HAL_OSPI_CLOCK_MODE_0 : HAL_OSPI_CLOCK_MODE_3;
obj->handle.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
obj->handle.Init.ChipSelectBoundary = 0;
#if defined(HAL_OSPI_DELAY_BLOCK_USED) // STM32L5
obj->handle.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_USED;
#endif
// tested all combinations, take first
obj->ospi = pinmap->peripheral;
#if defined(OCTOSPI1)
if (obj->ospi == OSPI_1) {
obj->handle.Instance = OCTOSPI1;
}
#endif
#if defined(OCTOSPI2)
if (obj->ospi == OSPI_2) {
obj->handle.Instance = OCTOSPI2;
}
#endif
#if defined(OCTOSPI1)
if (obj->ospi == OSPI_1) {
__HAL_RCC_OSPI1_CLK_ENABLE();
__HAL_RCC_OSPI1_FORCE_RESET();
__HAL_RCC_OSPI1_RELEASE_RESET();
}
#endif
#if defined(OCTOSPI2)
if (obj->ospi == OSPI_2) {
__HAL_RCC_OSPI2_CLK_ENABLE();
__HAL_RCC_OSPI2_FORCE_RESET();
__HAL_RCC_OSPI2_RELEASE_RESET();
}
#endif
// pinmap for pins (enable clock)
obj->io0 = pinmap->data0_pin;
pin_function(pinmap->data0_pin, pinmap->data0_function);
pin_mode(pinmap->data0_pin, PullNone);
obj->io1 = pinmap->data1_pin;
pin_function(pinmap->data1_pin, pinmap->data1_function);
pin_mode(pinmap->data1_pin, PullNone);
obj->io2 = pinmap->data2_pin;
pin_function(pinmap->data2_pin, pinmap->data2_function);
pin_mode(pinmap->data2_pin, PullNone);
obj->io3 = pinmap->data3_pin;
pin_function(pinmap->data3_pin, pinmap->data3_function);
pin_mode(pinmap->data3_pin, PullNone);
obj->io4 = pinmap->data4_pin;
pin_function(pinmap->data4_pin, pinmap->data4_function);
pin_mode(pinmap->data4_pin, PullNone);
obj->io5 = pinmap->data5_pin;
pin_function(pinmap->data5_pin, pinmap->data5_function);
pin_mode(pinmap->data5_pin, PullNone);
obj->io6 = pinmap->data6_pin;
pin_function(pinmap->data6_pin, pinmap->data6_function);
pin_mode(pinmap->data6_pin, PullNone);
obj->io7 = pinmap->data7_pin;
pin_function(pinmap->data7_pin, pinmap->data7_function);
pin_mode(pinmap->data7_pin, PullNone);
obj->sclk = pinmap->sclk_pin;
pin_function(pinmap->sclk_pin, pinmap->sclk_function);
pin_mode(pinmap->sclk_pin, PullNone);
obj->ssel = pinmap->ssel_pin;
pin_function(pinmap->ssel_pin, pinmap->ssel_function);
pin_mode(pinmap->ssel_pin, PullNone);
obj->dqs = pinmap->dqs_pin;
pin_function(pinmap->dqs_pin, pinmap->dqs_function);
pin_mode(pinmap->dqs_pin, PullNone);
#if defined(OCTOSPI2)
__HAL_RCC_OSPIM_CLK_ENABLE();
OSPIM_CfgTypeDef OSPIM_Cfg_Struct = {0};
/* The OctoSPI IO Manager OCTOSPIM configuration is supported in a simplified mode in mbed-os
* OSPI1 signals are mapped to port 1 and OSPI2 signals are mapped to port 2.
* This is coded in this way in PeripheralPins.c */
if (obj->ospi == OSPI_1) {
OSPIM_Cfg_Struct.ClkPort = 1;
OSPIM_Cfg_Struct.DQSPort = 1;
OSPIM_Cfg_Struct.NCSPort = 1;
OSPIM_Cfg_Struct.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
OSPIM_Cfg_Struct.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;
} else {
OSPIM_Cfg_Struct.ClkPort = 2;
OSPIM_Cfg_Struct.DQSPort = 2;
OSPIM_Cfg_Struct.NCSPort = 2;
OSPIM_Cfg_Struct.IOLowPort = HAL_OSPIM_IOPORT_2_LOW;
OSPIM_Cfg_Struct.IOHighPort = HAL_OSPIM_IOPORT_2_HIGH;
}
if (HAL_OSPIM_Config(&obj->handle, &OSPIM_Cfg_Struct, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
tr_error("HAL_OSPIM_Config error");
return OSPI_STATUS_ERROR;
}
#endif
return ospi_frequency(obj, hz);
}
ospi_status_t ospi_init(ospi_t *obj, PinName io0, PinName io1, PinName io2, PinName io3, PinName io4, PinName io5, PinName io6, PinName io7,
PinName sclk, PinName ssel, PinName dqs, uint32_t hz, uint8_t mode)
{
OSPIName ospiio0name = (OSPIName)pinmap_peripheral(io0, PinMap_OSPI_DATA0);
OSPIName ospiio1name = (OSPIName)pinmap_peripheral(io1, PinMap_OSPI_DATA1);
OSPIName ospiio2name = (OSPIName)pinmap_peripheral(io2, PinMap_OSPI_DATA2);
OSPIName ospiio3name = (OSPIName)pinmap_peripheral(io3, PinMap_OSPI_DATA3);
OSPIName ospiio4name = (OSPIName)pinmap_peripheral(io4, PinMap_OSPI_DATA4);
OSPIName ospiio5name = (OSPIName)pinmap_peripheral(io5, PinMap_OSPI_DATA5);
OSPIName ospiio6name = (OSPIName)pinmap_peripheral(io6, PinMap_OSPI_DATA6);
OSPIName ospiio7name = (OSPIName)pinmap_peripheral(io7, PinMap_OSPI_DATA7);
OSPIName ospiclkname = (OSPIName)pinmap_peripheral(sclk, PinMap_OSPI_SCLK);
OSPIName ospisselname = (OSPIName)pinmap_peripheral(ssel, PinMap_OSPI_SSEL);
OSPIName ospidqsname = (OSPIName)pinmap_peripheral(dqs, PinMap_OSPI_DQS);
OSPIName ospi_data_first = (OSPIName)pinmap_merge(ospiio0name, ospiio1name);
OSPIName ospi_data_second = (OSPIName)pinmap_merge(ospiio2name, ospiio3name);
OSPIName ospi_data_third = (OSPIName)pinmap_merge(ospiclkname, ospisselname);
if (ospi_data_first != ospi_data_second || ospi_data_second != ospi_data_third ||
ospi_data_first != ospi_data_third) {
return OSPI_STATUS_INVALID_PARAMETER;
}
int peripheral = (int)ospi_data_first;
int function_io0 = (int)pinmap_find_function(io0, PinMap_OSPI_DATA0);
int function_io1 = (int)pinmap_find_function(io1, PinMap_OSPI_DATA1);
int function_io2 = (int)pinmap_find_function(io2, PinMap_OSPI_DATA2);
int function_io3 = (int)pinmap_find_function(io3, PinMap_OSPI_DATA3);
int function_io4 = (int)pinmap_find_function(io4, PinMap_OSPI_DATA4);
int function_io5 = (int)pinmap_find_function(io5, PinMap_OSPI_DATA5);
int function_io6 = (int)pinmap_find_function(io6, PinMap_OSPI_DATA6);
int function_io7 = (int)pinmap_find_function(io7, PinMap_OSPI_DATA7);
int function_sclk = (int)pinmap_find_function(sclk, PinMap_OSPI_SCLK);
int function_ssel = (int)pinmap_find_function(ssel, PinMap_OSPI_SSEL);
int function_dqs = (int)pinmap_find_function(dqs, PinMap_OSPI_DQS);
const ospi_pinmap_t static_pinmap = {peripheral, io0, function_io0, io1, function_io1, io2, function_io2, io3, function_io3,
io4, function_io4, io5, function_io5, io6, function_io6, io7, function_io7,
sclk, function_sclk, ssel, function_ssel, dqs, function_dqs};
return OSPI_INIT_DIRECT(obj, &static_pinmap, hz, mode);
}
ospi_status_t ospi_free(ospi_t *obj)
{
tr_info("ospi_free");
if (HAL_OSPI_DeInit(&obj->handle) != HAL_OK) {
return OSPI_STATUS_ERROR;
}
#if defined(OCTOSPI1)
if (obj->ospi == OSPI_1) {
__HAL_RCC_OSPI1_FORCE_RESET();
__HAL_RCC_OSPI1_CLK_DISABLE();
}
#endif
#if defined(OCTOSPI2)
if (obj->ospi == OSPI_2) {
__HAL_RCC_OSPI2_FORCE_RESET();
__HAL_RCC_OSPI2_CLK_DISABLE();
}
#endif
// Configure GPIOs
pin_function(obj->io0, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
pin_function(obj->io1, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
pin_function(obj->io2, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
pin_function(obj->io3, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
pin_function(obj->io4, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
pin_function(obj->io5, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
pin_function(obj->io6, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
pin_function(obj->io7, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
pin_function(obj->sclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
pin_function(obj->ssel, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
pin_function(obj->dqs, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
(void)(obj);
return OSPI_STATUS_OK;
}
ospi_status_t ospi_frequency(ospi_t *obj, int hz)
{
tr_info("ospi_frequency hz %d", hz);
ospi_status_t status = OSPI_STATUS_OK;
/* HCLK drives OSPI. OSPI clock depends on prescaler value:
* 0: Freq = HCLK
* 1: Freq = HCLK/2
* ...
* 255: Freq = HCLK/256 (minimum value)
*/
int div = HAL_RCC_GetHCLKFreq() / hz;
if (div > 255) {
div = 255;
} else {
if (div == 1) {
div = div + 1;
}
}
obj->handle.Init.ClockPrescaler = div;
if (HAL_OSPI_Init(&obj->handle) != HAL_OK) {
tr_error("HAL_OSPI_Init error");
status = OSPI_STATUS_ERROR;
}
return status;
}
ospi_status_t ospi_write(ospi_t *obj, const ospi_command_t *command, const void *data, size_t *length)
{
debug_if(ospi_api_c_debug, "ospi_write size %u\n", *length);
OSPI_RegularCmdTypeDef st_command;
ospi_status_t status = ospi_prepare_command(command, &st_command);
if (status != OSPI_STATUS_OK) {
return status;
}
st_command.NbData = *length;
if (HAL_OSPI_Command(&obj->handle, &st_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
tr_error("HAL_OSPI_Command error");
status = OSPI_STATUS_ERROR;
} else {
if (HAL_OSPI_Transmit(&obj->handle, (uint8_t *)data, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
tr_error("HAL_OSPI_Transmit error");
status = OSPI_STATUS_ERROR;
}
}
return status;
}
ospi_status_t ospi_read(ospi_t *obj, const ospi_command_t *command, void *data, size_t *length)
{
OSPI_RegularCmdTypeDef st_command;
ospi_status_t status = ospi_prepare_command(command, &st_command);
if (status != OSPI_STATUS_OK) {
return status;
}
st_command.NbData = *length;
if (HAL_OSPI_Command(&obj->handle, &st_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
tr_error("HAL_OSPI_Command error");
status = OSPI_STATUS_ERROR;
} else {
if (HAL_OSPI_Receive(&obj->handle, data, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
tr_error("HAL_OSPI_Receive error %d", obj->handle.ErrorCode);
status = OSPI_STATUS_ERROR;
}
}
debug_if(ospi_api_c_debug, "ospi_read size %u\n", *length);
return status;
}
ospi_status_t ospi_command_transfer(ospi_t *obj, const ospi_command_t *command, const void *tx_data, size_t tx_size, void *rx_data, size_t rx_size)
{
tr_info("ospi_command_transfer tx %u rx %u command %#04x", tx_size, rx_size, command->instruction.value);
ospi_status_t status = OSPI_STATUS_OK;
if ((tx_data == NULL || tx_size == 0) && (rx_data == NULL || rx_size == 0)) {
// only command, no rx or tx
OSPI_RegularCmdTypeDef st_command;
status = ospi_prepare_command(command, &st_command);
if (status != OSPI_STATUS_OK) {
return status;
}
st_command.NbData = 1;
st_command.DataMode = HAL_OSPI_DATA_NONE; /* Instruction only */
if (HAL_OSPI_Command(&obj->handle, &st_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
status = OSPI_STATUS_ERROR;
tr_error("HAL_OSPI_Command error");
return status;
}
} else {
// often just read a register, check if we need to transmit anything prior reading
if (tx_data != NULL && tx_size) {
size_t tx_length = tx_size;
status = ospi_write(obj, command, tx_data, &tx_length);
if (status != OSPI_STATUS_OK) {
tr_error("qspi_write error");
return status;
}
}
if (rx_data != NULL && rx_size) {
size_t rx_length = rx_size;
status = ospi_read(obj, command, rx_data, &rx_length);
}
}
return status;
}
const PinMap *ospi_master_sclk_pinmap()
{
return PinMap_OSPI_SCLK;
}
const PinMap *ospi_master_ssel_pinmap()
{
return PinMap_OSPI_SSEL;
}
const PinMap *ospi_master_dqs_pinmap()
{
return PinMap_OSPI_DQS;
}
const PinMap *ospi_master_data0_pinmap()
{
return PinMap_OSPI_DATA0;
}
const PinMap *ospi_master_data1_pinmap()
{
return PinMap_OSPI_DATA1;
}
const PinMap *ospi_master_data2_pinmap()
{
return PinMap_OSPI_DATA2;
}
const PinMap *ospi_master_data3_pinmap()
{
return PinMap_OSPI_DATA3;
}
const PinMap *ospi_master_data4_pinmap()
{
return PinMap_OSPI_DATA4;
}
const PinMap *ospi_master_data5_pinmap()
{
return PinMap_OSPI_DATA5;
}
const PinMap *ospi_master_data6_pinmap()
{
return PinMap_OSPI_DATA6;
}
const PinMap *ospi_master_data7_pinmap()
{
return PinMap_OSPI_DATA7;
}
#endif
/** @}*/

View File

@ -3304,6 +3304,7 @@
"MX25LM51245G"
],
"components_add": [
"OSPIF",
"FLASHIAP"
],
"macros_add": [
@ -3314,7 +3315,7 @@
"0774"
],
"device_has_add": [
"QSPI",
"OSPI",
"USBDEVICE"
]
},