Merge pull request #11531 from kyle-cypress/pr/qspi-sfdp

Improve QSPIFBlockDevice conformance to SFDP
pull/11713/head
Martin Kojtal 2019-11-13 17:55:36 +01:00 committed by GitHub
commit 539779fa58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 959 additions and 590 deletions

View File

@ -84,6 +84,7 @@ static uint32_t gen_flash_address()
{
srand(ticker_read(get_us_ticker_data()));
uint32_t address = (((uint32_t)rand()) % QSPI_SECTOR_COUNT) * QSPI_SECTOR_SIZE;
address &= 0xFFFFFF; // Ensure address is within 24 bits so as to not have to deal with 4-byte addressing
return address;
}

View File

@ -58,7 +58,7 @@ void QspiCommand::set_dummy_cycles(int dummy_cycles)
void QspiCommand::build(int instruction, int address, int alt)
{
_cmd.instruction.disabled = (instruction == QSPI_NONE);
_cmd.instruction.disabled = (instruction == QSPI_NO_INST);
if (!_cmd.instruction.disabled) {
_cmd.instruction.value = instruction;
}
@ -127,17 +127,33 @@ void flash_init(Qspi &qspi)
ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, status, QSPI_STATUS_REG_SIZE);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
qspi.cmd.build(QSPI_CMD_RSTEN);
ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
// Only do reset enable if device needs it
if (QSPI_CMD_RSTEN != 0) {
qspi.cmd.build(QSPI_CMD_RSTEN);
ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
WAIT_FOR(WRSR_MAX_TIME, qspi);
WAIT_FOR(WRSR_MAX_TIME, qspi);
}
qspi.cmd.build(QSPI_CMD_RST);
ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
WAIT_FOR(WAIT_MAX_TIME, qspi);
// Zero out status register to attempt to clear block protection bits
uint8_t blanks[QSPI_STATUS_REG_SIZE] = {0};
qspi.cmd.build(QSPI_CMD_WREN);
ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
qspi.cmd.build(QSPI_CMD_WRSR);
ret = qspi_command_transfer(&qspi.handle, qspi.cmd.get(), blanks, 1, NULL, 0);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
WAIT_FOR(WRSR_MAX_TIME, qspi);
}

View File

@ -27,11 +27,11 @@ enum qspif_bd_error {
QSPIF_BD_ERROR_OK = 0, /*!< no error */
QSPIF_BD_ERROR_DEVICE_ERROR = BD_ERROR_DEVICE_ERROR, /*!< device specific error -4001 */
QSPIF_BD_ERROR_PARSING_FAILED = -4002, /* SFDP Parsing failed */
QSPIF_BD_ERROR_READY_FAILED = -4003, /* Wait for Mem Ready failed */
QSPIF_BD_ERROR_READY_FAILED = -4003, /* Wait for Mem Ready failed */
QSPIF_BD_ERROR_WREN_FAILED = -4004, /* Write Enable Failed */
QSPIF_BD_ERROR_INVALID_ERASE_PARAMS = -4005, /* Erase command not on sector aligned addresses or exceeds device size */
QSPIF_BD_ERROR_DEVICE_NOT_UNIQE = -4006, /* Only one instance per csel is allowed */
QSPIF_BD_ERROR_DEVICE_MAX_EXCEED = -4007 /* Max active QSPIF devices exceeded */
QSPIF_BD_ERROR_DEVICE_NOT_UNIQUE = -4006, /* Only one instance per csel is allowed */
QSPIF_BD_ERROR_DEVICE_MAX_EXCEED = -4007 /* Max active QSPIF devices exceeded */
};
/** Enum qspif polarity mode
@ -248,19 +248,26 @@ private:
qspi_status_t _qspi_send_general_command(mbed::qspi_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 Bus configure_format command to Driver
qspi_status_t _qspi_configure_format(qspi_bus_width_t inst_width, qspi_bus_width_t address_width,
qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width,
int dummy_cycles);
// Send command to read from the SFDP table
qspi_status_t _qspi_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)
qspi_status_t _qspi_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)
qspi_status_t _qspi_write_status_registers(uint8_t *reg_buffer);
// Send set_frequency command to Driver
qspi_status_t _qspi_set_frequency(int freq);
// Update the 4-byte addressing extension register with the MSB of the address if it is in use
qspi_status_t _qspi_update_4byte_ext_addr_reg(bd_addr_t addr);
/*********************************/
/* Flash Configuration Functions */
/*********************************/
// Soft Reset Flash Memory
int _reset_flash_mem();
// Clear the device's block protection
int _clear_block_protection();
// Configure Write Enable in Status Register
int _set_write_enable();
@ -269,7 +276,7 @@ private:
bool _is_mem_ready();
// Enable Fast Mode - for flash chips with low power default
int _enable_fast_mdoe();
int _enable_fast_mode();
/****************************************/
/* SFDP Detection and Parsing Functions */
@ -281,26 +288,33 @@ private:
// Parse and Detect required Basic Parameters from Table
int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size);
// Parse and read information required by Regions Secotr Map
// Parse and read information required by Regions Sector Map
int _sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size);
// 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, mbed::qspi_inst_t &read_inst);
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);
// 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) is supported
// Enable QPI mode (4-4-4)
int _sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr);
// Set Page size for program
int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size);
// Detect all supported erase types
int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size,
mbed::qspi_inst_t &erase4k_inst,
mbed::qspi_inst_t *erase_type_inst_arr, unsigned int *erase_type_size_arr);
int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size);
// 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);
// Query vendor ID and handle special behavior that isn't covered by SFDP data
int _handle_vendor_quirks();
/***********************/
/* Utilities Functions */
@ -313,6 +327,11 @@ private:
int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry);
private:
enum qspif_clear_protection_method_t {
QSPIF_BP_ULBPR, // Issue global protection unlock instruction
QSPIF_BP_CLEAR_SR, // Clear protection bits in status register 1
};
// QSPI Driver Object
mbed::QSPI _qspi;
@ -332,16 +351,31 @@ private:
// Command Instructions
mbed::qspi_inst_t _read_instruction;
mbed::qspi_inst_t _prog_instruction;
mbed::qspi_inst_t _erase_instruction;
mbed::qspi_inst_t _erase4k_inst; // Legacy 4K erase instruction (default 0x20h)
mbed::qspi_inst_t _write_register_inst; // Write status/config register instruction may vary between chips
mbed::qspi_inst_t _read_register_inst; // Read status/config register instruction may vary between chips
mbed::qspi_inst_t _legacy_erase_instruction;
// Status register write/read instructions
unsigned int _num_status_registers;
mbed::qspi_inst_t _write_status_reg_2_inst;
mbed::qspi_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::qspi_inst_t _4byte_msb_reg_write_inst;
// Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size)
mbed::qspi_inst_t _erase_type_inst_arr[MAX_NUM_OF_ERASE_TYPES];
unsigned int _erase_type_size_arr[MAX_NUM_OF_ERASE_TYPES];
// Quad mode enable status register and bit
int _quad_enable_register_idx;
int _quad_enable_bit;
bool _needs_fast_mode;
// Clear block protection
qspif_clear_protection_method_t _clear_protection_method;
// Sector Regions Map
int _regions_count; //number of regions
int _region_size_bytes[QSPIF_MAX_REGIONS]; //regions size in bytes

View File

@ -64,7 +64,7 @@ using namespace utest::v1;
#define TEST_BLOCK_COUNT 10
#define TEST_ERROR_MASK 16
#define TEST_NUM_OF_THREADS 5
#define TEST_THREAD_STACK_SIZE 1024
#define TEST_THREAD_STACK_SIZE 1152
uint8_t num_of_sectors = TEST_NUM_OF_THREADS * TEST_BLOCK_COUNT;
uint32_t sectors_addr[TEST_NUM_OF_THREADS * TEST_BLOCK_COUNT] = {0};

View File

@ -30,8 +30,8 @@
#include "utest.h"
#include <stdlib.h>
#if !defined(TARGET_K64F) && !defined(TARGET_ARM_FM)
#error [NOT_SUPPORTED] Kvstore API tests run only on K64F devices and Fastmodels
#if !defined(TARGET_K64F) && !defined(TARGET_ARM_FM) && !defined(TARGET_MCU_PSOC6)
#error [NOT_SUPPORTED] Kvstore API tests run only on K64F devices, Fastmodels, and PSoC 6
#else
#define FSST_TEST_NUM_OF_THREADS 5

View File

@ -32,8 +32,8 @@
using namespace utest::v1;
using namespace mbed;
#if !defined(TARGET_K64F) && !defined(TARGET_ARM_FM)
#error [NOT_SUPPORTED] Kvstore API tests run only on K64F devices and Fastmodels
#if !defined(TARGET_K64F) && !defined(TARGET_ARM_FM) && !defined(TARGET_MCU_PSOC6)
#error [NOT_SUPPORTED] Kvstore API tests run only on K64F devices, Fastmodels, and PSoC 6
#else
static const char data[] = "data";
@ -66,9 +66,6 @@ static const char *kv_prefix[] = {"TDB_", "FS_", "SEC_"};
static int kv_setup = TDBStoreSet;
static const size_t ul_bd_size = 16 * 4096;
static const size_t rbp_bd_size = 8 * 4096;
static const int heap_alloc_threshold_size = 4096;
/*----------------initialization------------------*/
@ -77,6 +74,8 @@ static const int heap_alloc_threshold_size = 4096;
static void kvstore_init()
{
int res;
size_t erase_size, ul_bd_size, rbp_bd_size;
BlockDevice *sec_bd;
res = bd->init();
TEST_ASSERT_EQUAL_ERROR_CODE(0, res);
@ -105,14 +104,19 @@ static void kvstore_init()
#if SECURESTORE_ENABLED
if (kv_setup == SecStoreSet) {
sec_bd = bd;
if (erase_val == -1) {
flash_bd = new FlashSimBlockDevice(bd);
ul_bd = new SlicingBlockDevice(flash_bd, 0, ul_bd_size);
rbp_bd = new SlicingBlockDevice(flash_bd, ul_bd_size, ul_bd_size + rbp_bd_size);
} else {
ul_bd = new SlicingBlockDevice(bd, 0, ul_bd_size);
rbp_bd = new SlicingBlockDevice(bd, ul_bd_size, ul_bd_size + rbp_bd_size);
sec_bd = flash_bd;
}
erase_size = sec_bd->get_erase_size();
ul_bd_size = erase_size * 4;
rbp_bd_size = erase_size * 2;
ul_bd = new SlicingBlockDevice(sec_bd, 0, ul_bd_size);
rbp_bd = new SlicingBlockDevice(sec_bd, ul_bd_size, ul_bd_size + rbp_bd_size);
TDBStore *ul_kv = new TDBStore(ul_bd);
TDBStore *rbp_kv = new TDBStore(rbp_bd);
kvstore = new SecureStore(ul_kv, rbp_kv);

View File

@ -32,8 +32,8 @@
using namespace utest::v1;
using namespace mbed;
#if !defined(TARGET_K64F) && !defined(TARGET_ARM_FM)
#error [NOT_SUPPORTED] Kvstore API tests run only on K64F devices and Fastmodels
#if !defined(TARGET_K64F) && !defined(TARGET_ARM_FM) && !defined(TARGET_MCU_PSOC6)
#error [NOT_SUPPORTED] Kvstore API tests run only on K64F devices, Fastmodels, and PSoC 6
#else
static const char data[] = "data";
@ -66,9 +66,6 @@ static const char *kv_prefix[] = {"TDB_", "FS_", "SEC_"};
static int kv_setup = TDBStoreSet;
static const size_t ul_bd_size = 16 * 4096;
static const size_t rbp_bd_size = 8 * 4096;
static const int heap_alloc_threshold_size = 4096;
/*----------------initialization------------------*/
@ -77,6 +74,8 @@ static const int heap_alloc_threshold_size = 4096;
static void kvstore_init()
{
int res;
size_t erase_size, ul_bd_size, rbp_bd_size;
BlockDevice *sec_bd;
res = bd->init();
TEST_ASSERT_EQUAL_ERROR_CODE(0, res);
@ -105,14 +104,19 @@ static void kvstore_init()
#if SECURESTORE_ENABLED
if (kv_setup == SecStoreSet) {
sec_bd = bd;
if (erase_val == -1) {
flash_bd = new FlashSimBlockDevice(bd);
ul_bd = new SlicingBlockDevice(flash_bd, 0, ul_bd_size);
rbp_bd = new SlicingBlockDevice(flash_bd, ul_bd_size, ul_bd_size + rbp_bd_size);
} else {
ul_bd = new SlicingBlockDevice(bd, 0, ul_bd_size);
rbp_bd = new SlicingBlockDevice(bd, ul_bd_size, ul_bd_size + rbp_bd_size);
sec_bd = flash_bd;
}
erase_size = sec_bd->get_erase_size();
ul_bd_size = erase_size * 4;
rbp_bd_size = erase_size * 2;
ul_bd = new SlicingBlockDevice(sec_bd, 0, ul_bd_size);
rbp_bd = new SlicingBlockDevice(sec_bd, ul_bd_size, ul_bd_size + rbp_bd_size);
TDBStore *ul_kv = new TDBStore(ul_bd);
TDBStore *rbp_kv = new TDBStore(rbp_bd);
kvstore = new SecureStore(ul_kv, rbp_kv);

View File

@ -34,8 +34,8 @@
#include <stdio.h>
#include <algorithm>
#if (!defined(TARGET_K64F) && !defined(TARGET_ARM_FM)) || !SECURESTORE_ENABLED
#error [NOT_SUPPORTED] Kvstore API tests run only on K64F devices and Fastmodels. KVStore & SecureStore need to be enabled for this test
#if (!defined(TARGET_K64F) && !defined(TARGET_ARM_FM)) && !defined(TARGET_MCU_PSOC6) || !SECURESTORE_ENABLED
#error [NOT_SUPPORTED] Kvstore API tests run only on K64F devices, Fastmodels, and PSoC 6. KVStore & SecureStore need to be enabled for this test
#else
using namespace mbed;

View File

@ -92,8 +92,8 @@ static const char *const res_val2 = "This should surely not be saved as the res
static void white_box_test()
{
#if !defined(TARGET_K64F)
TEST_SKIP_MESSAGE("Kvstore API tests run only on K64F devices");
#if !defined(TARGET_K64F) && !defined(TARGET_MCU_PSOC6)
TEST_SKIP_MESSAGE("Kvstore API tests run only on K64F devices and PSoC 6");
#endif
bd_params_t bd_params[] = {
@ -334,8 +334,8 @@ static void white_box_test()
static void multi_set_test()
{
#if !defined(TARGET_K64F)
TEST_SKIP_MESSAGE("Kvstore API tests run only on K64F devices");
#if !defined(TARGET_K64F) && !defined(TARGET_MCU_PSOC6)
TEST_SKIP_MESSAGE("Kvstore API tests run only on K64F devices and PSoC 6");
#endif
char *key;
@ -458,8 +458,8 @@ static void multi_set_test()
static void error_inject_test()
{
#if !defined(TARGET_K64F)
TEST_SKIP_MESSAGE("Kvstore API tests run only on K64F devices");
#if !defined(TARGET_K64F) && !defined(TARGET_MCU_PSOC6)
TEST_SKIP_MESSAGE("Kvstore API tests run only on K64F devices and PSoC 6");
#endif
char *key;