From 6a6904043c0408920d2653916af4bd942065d210 Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Tue, 21 Jan 2020 12:42:13 +0200 Subject: [PATCH 01/12] QSPIFBlockDevice: drops unnecessary wrapper function --- .../blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp | 7 +------ .../storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h | 3 --- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index 24bc51a7745..fd8c19d4a9f 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -249,7 +249,7 @@ int QSPIFBlockDevice::init() } /**************************** Parse SFDP Header ***********************************/ - if (0 != _sfdp_parse_sfdp_headers(hdr_info)) { + if (sfdp_parse_headers(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), hdr_info) < 0) { tr_error("Init - Parse SFDP Headers Failed"); status = QSPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -627,11 +627,6 @@ int QSPIFBlockDevice::remove_csel_instance(PinName csel) /*********************************************************/ /********** SFDP Parsing and Detection Functions *********/ /*********************************************************/ -int QSPIFBlockDevice::_sfdp_parse_sfdp_headers(mbed::sfdp_hdr_info &hdr_info) -{ - return sfdp_parse_headers(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), hdr_info); -} - int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size) { uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */ diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h index a3ca84ada2c..2af2493e1c0 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h @@ -318,9 +318,6 @@ class QSPIFBlockDevice : public mbed::BlockDevice { /****************************************/ /* SFDP Detection and Parsing Functions */ /****************************************/ - // Parse SFDP Headers and retrieve Basic Param and Sector Map Tables (if exist) - int _sfdp_parse_sfdp_headers(mbed::sfdp_hdr_info &hdr_info); - // Parse and Detect required Basic Parameters from Table int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size); From 4e1fb076337b57dcd546ac26f0e01020058dc4c2 Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Tue, 21 Jan 2020 13:23:36 +0200 Subject: [PATCH 02/12] SFDP: reorganizes internal info structure --- .../COMPONENT_QSPIF/QSPIFBlockDevice.cpp | 10 +++++----- .../COMPONENT_SPIF/SPIFBlockDevice.cpp | 10 +++++----- drivers/internal/SFDP.h | 18 ++++++++++++++---- drivers/source/SFDP.cpp | 8 ++++---- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index fd8c19d4a9f..1150e5294a6 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -256,7 +256,7 @@ int QSPIFBlockDevice::init() } /**************************** Parse Basic Parameters Table ***********************************/ - if (0 != _sfdp_parse_basic_param_table(hdr_info.basic_table_addr, hdr_info.basic_table_size)) { + if (0 != _sfdp_parse_basic_param_table(hdr_info.bptbl.addr, hdr_info.bptbl.size)) { tr_error("Init - Parse Basic Param Table Failed"); status = QSPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -267,10 +267,10 @@ int QSPIFBlockDevice::init() _device_size_bytes; // If there's no region map, we have a single region sized the entire device size _region_high_boundary[0] = _device_size_bytes - 1; - if ((hdr_info.sector_map_table_addr != 0) && (0 != hdr_info.sector_map_table_size)) { - tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", hdr_info.sector_map_table_addr, - hdr_info.sector_map_table_size); - if (0 != _sfdp_parse_sector_map_table(hdr_info.sector_map_table_addr, hdr_info.sector_map_table_size)) { + if ((hdr_info.smtbl.addr != 0) && (0 != hdr_info.smtbl.size)) { + tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", hdr_info.smtbl.addr, + hdr_info.smtbl.size); + if (0 != _sfdp_parse_sector_map_table(hdr_info.smtbl.addr, hdr_info.smtbl.size)) { tr_error("Init - Parse Sector Map Table Failed"); status = QSPIF_BD_ERROR_PARSING_FAILED; goto exit_point; diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp index 3d2966dec26..b10574ae5e4 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp @@ -189,7 +189,7 @@ int SPIFBlockDevice::init() /**************************** Parse Basic Parameters Table ***********************************/ - if (0 != _sfdp_parse_basic_param_table(hdr_info.basic_table_addr, hdr_info.basic_table_size)) { + if (0 != _sfdp_parse_basic_param_table(hdr_info.bptbl.addr, hdr_info.bptbl.size)) { tr_error("init - Parse Basic Param Table Failed"); status = SPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -200,10 +200,10 @@ int SPIFBlockDevice::init() _device_size_bytes; // If there's no region map, we have a single region sized the entire device size _region_high_boundary[0] = _device_size_bytes - 1; - if ((hdr_info.sector_map_table_addr != 0) && (0 != hdr_info.sector_map_table_size)) { - tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", hdr_info.sector_map_table_addr, - hdr_info.sector_map_table_size); - if (0 != _sfdp_parse_sector_map_table(hdr_info.sector_map_table_addr, hdr_info.sector_map_table_size)) { + if ((hdr_info.smtbl.addr != 0) && (0 != hdr_info.smtbl.size)) { + tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", hdr_info.smtbl.addr, + hdr_info.smtbl.size); + if (0 != _sfdp_parse_sector_map_table(hdr_info.smtbl.addr, hdr_info.smtbl.size)) { tr_error("init - Parse Sector Map Table Failed"); status = SPIF_BD_ERROR_PARSING_FAILED; goto exit_point; diff --git a/drivers/internal/SFDP.h b/drivers/internal/SFDP.h index 012b033a6f6..9951df792fd 100644 --- a/drivers/internal/SFDP.h +++ b/drivers/internal/SFDP.h @@ -28,12 +28,22 @@ namespace mbed { static const int SFDP_HEADER_SIZE = 8; ///< Size of an SFDP header */ static const int SFDP_BASIC_PARAMS_TBL_SIZE = 80; ///< Basic Parameter Table size in Bytes, 20 DWORDS */ +/** SFDP Basic Parameter Table info */ +struct sfdp_bptbl_info { + uint32_t addr; + size_t size; +}; + +/** SFDP Sector Map Table info */ +struct sfdp_smtbl_info { + uint32_t addr; + size_t size; +}; + /** SFDP Parameter Table addresses and sizes */ struct sfdp_hdr_info { - uint32_t basic_table_addr; // Basic Parameter Table address - size_t basic_table_size; // Basic Parameter Table size - uint32_t sector_map_table_addr; // Sector Map Parameter Table address - size_t sector_map_table_size; // Sector Map Parameter Table size + sfdp_bptbl_info bptbl; + sfdp_smtbl_info smtbl; }; /** SFDP Header */ diff --git a/drivers/source/SFDP.cpp b/drivers/source/SFDP.cpp index 28ef8955433..f4f29f738a7 100644 --- a/drivers/source/SFDP.cpp +++ b/drivers/source/SFDP.cpp @@ -67,13 +67,13 @@ int sfdp_parse_single_param_header(sfdp_prm_hdr *phdr, sfdp_hdr_info &hdr_info) if ((phdr->PID_LSB == 0) && (sfdp_get_param_id_msb(phdr->DWORD2) == 0xFF)) { tr_debug("Parameter Header: Basic Parameter Header"); - hdr_info.basic_table_addr = sfdp_get_param_tbl_ptr(phdr->DWORD2); - hdr_info.basic_table_size = std::min((phdr->P_LEN * 4), SFDP_BASIC_PARAMS_TBL_SIZE); + hdr_info.bptbl.addr = sfdp_get_param_tbl_ptr(phdr->DWORD2); + hdr_info.bptbl.size = std::min((phdr->P_LEN * 4), SFDP_BASIC_PARAMS_TBL_SIZE); } else if ((phdr->PID_LSB == 0x81) && (sfdp_get_param_id_msb(phdr->DWORD2) == 0xFF)) { tr_debug("Parameter Header: Sector Map Parameter Header"); - hdr_info.sector_map_table_addr = sfdp_get_param_tbl_ptr(phdr->DWORD2); - hdr_info.sector_map_table_size = phdr->P_LEN * 4; + hdr_info.smtbl.addr = sfdp_get_param_tbl_ptr(phdr->DWORD2); + hdr_info.smtbl.size = phdr->P_LEN * 4; } else { tr_debug("Parameter Header vendor specific or unknown. Parameter ID LSB: 0x%" PRIX8 "; MSB: 0x%" PRIX8 "", From cba5bfc79055f0d94f63be41568eade6329ab08d Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Tue, 21 Jan 2020 17:13:06 +0200 Subject: [PATCH 03/12] QSPIFBlockDevice: Reads Sector Map Table by using a SFDP Reader cb --- .../COMPONENT_QSPIF/QSPIFBlockDevice.cpp | 15 ++++++++------- .../COMPONENT_QSPIF/QSPIFBlockDevice.h | 3 ++- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index 1150e5294a6..698c669532a 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -53,7 +53,6 @@ using namespace mbed; /* Basic Parameters Table Parsing */ /**********************************/ -#define SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES 64 /* 16 DWORDS */ //READ Instruction support according to BUS Configuration #define QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE 2 #define QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE 16 @@ -270,7 +269,8 @@ int QSPIFBlockDevice::init() if ((hdr_info.smtbl.addr != 0) && (0 != hdr_info.smtbl.size)) { tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", hdr_info.smtbl.addr, hdr_info.smtbl.size); - if (0 != _sfdp_parse_sector_map_table(hdr_info.smtbl.addr, hdr_info.smtbl.size)) { + if (_sfdp_parse_sector_map_table(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), + hdr_info.smtbl) < 0) { tr_error("Init - Parse Sector Map Table Failed"); status = QSPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -629,7 +629,7 @@ int QSPIFBlockDevice::remove_csel_instance(PinName csel) /*********************************************************/ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size) { - uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */ + uint8_t param_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 16 DWORDS = 64 Bytes */ int status = _qspi_send_read_sfdp_command(basic_table_addr, (char *)param_table, basic_table_size); if (status != QSPI_STATUS_OK) { @@ -1103,17 +1103,18 @@ int QSPIFBlockDevice::_sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param return status; } -int QSPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size) +int QSPIFBlockDevice::_sfdp_parse_sector_map_table(Callback sfdp_reader, + sfdp_smtbl_info &smtbl) { - uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */ + uint8_t sector_map_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 16 DWORDS = 64 Bytes */ uint32_t tmp_region_size = 0; int i_ind = 0; int prev_boundary = 0; // Default set to all type bits 1-4 are common int min_common_erase_type_bits = ERASE_BITMASK_ALL; - int status = _qspi_send_read_sfdp_command(sector_map_table_addr, (char *)sector_map_table, sector_map_table_size); - if (status != QSPI_STATUS_OK) { + int status = sfdp_reader(smtbl.addr, sector_map_table, smtbl.size); + if (status < 0) { tr_error("Init - Read SFDP First Table Failed"); return -1; } diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h index 2af2493e1c0..2e41b9489b4 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h @@ -322,7 +322,8 @@ class QSPIFBlockDevice : public mbed::BlockDevice { int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size); // 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); + int _sfdp_parse_sector_map_table(mbed::Callback sfdp_reader, + mbed::sfdp_smtbl_info &smtbl); // 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); From 6108f384fb08cf405e2c426052a8bd4ae7dcb117 Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Wed, 22 Jan 2020 09:41:58 +0200 Subject: [PATCH 04/12] QSPIFBlockDevice: Consolidates SFDP info data This far all SFDP Sector Map Table related data has been found in small pieces inside QSPIFBlockDevice. Purpose was to consolidate the data under one SFDP structure where all the information gathered from SFDP tables is stored. Parsing a Sector Map Table was made more generic so that later it can be moved under SFDP module. Once that is done it can be shared with SPIFBlockDevice to avoid code duplication. --- .../COMPONENT_QSPIF/QSPIFBlockDevice.cpp | 146 ++++++++++-------- .../COMPONENT_QSPIF/QSPIFBlockDevice.h | 27 ++-- .../COMPONENT_SPIF/SPIFBlockDevice.cpp | 16 +- drivers/internal/SFDP.h | 20 +++ drivers/source/SFDP.cpp | 5 + 5 files changed, 119 insertions(+), 95 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index 698c669532a..1e04235cc03 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -83,11 +83,6 @@ using namespace mbed; #define SOFT_RESET_RESET_INST_BITMASK 0b001000 #define SOFT_RESET_ENABLE_AND_RESET_INST_BITMASK 0b010000 -// Erase Types Per Region BitMask -#define ERASE_BITMASK_TYPE4 0x08 -#define ERASE_BITMASK_TYPE1 0x01 -#define ERASE_BITMASK_NONE 0x00 -#define ERASE_BITMASK_ALL 0x0F // 4-Byte Addressing Support Bitmasks #define FOURBYTE_ADDR_B7_BITMASK 0b00000001 @@ -157,9 +152,9 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam } // Initialize parameters - _min_common_erase_size = 0; - _regions_count = 1; - _region_erase_types_bitfield[0] = ERASE_BITMASK_NONE; + _sfdp_info.smtbl._min_common_erase_size = 0; + _sfdp_info.smtbl._regions_count = 1; + _sfdp_info.smtbl._region_erase_types_bitfield[0] = SFDP_ERASE_BITMASK_NONE; // Until proven otherwise, assume no quad enable _quad_enable_register_idx = QSPIF_NO_QUAD_ENABLE; @@ -203,8 +198,10 @@ int QSPIFBlockDevice::init() } int status = QSPIF_BD_ERROR_OK; - sfdp_hdr_info hdr_info; - memset(&hdr_info, 0, sizeof hdr_info); + _sfdp_info.bptbl.addr = 0x0; + _sfdp_info.bptbl.size = 0; + _sfdp_info.smtbl.addr = 0x0; + _sfdp_info.smtbl.size = 0; _mutex.lock(); @@ -248,29 +245,29 @@ int QSPIFBlockDevice::init() } /**************************** Parse SFDP Header ***********************************/ - if (sfdp_parse_headers(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), hdr_info) < 0) { + if (sfdp_parse_headers(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), _sfdp_info) < 0) { tr_error("Init - Parse SFDP Headers Failed"); status = QSPIF_BD_ERROR_PARSING_FAILED; goto exit_point; } /**************************** Parse Basic Parameters Table ***********************************/ - if (0 != _sfdp_parse_basic_param_table(hdr_info.bptbl.addr, hdr_info.bptbl.size)) { + if (0 != _sfdp_parse_basic_param_table(_sfdp_info.bptbl.addr, _sfdp_info.bptbl.size)) { tr_error("Init - Parse Basic Param Table Failed"); status = QSPIF_BD_ERROR_PARSING_FAILED; goto exit_point; } /**************************** Parse Sector Map Table ***********************************/ - _region_size_bytes[0] = + _sfdp_info.smtbl._region_size_bytes[0] = _device_size_bytes; // If there's no region map, we have a single region sized the entire device size - _region_high_boundary[0] = _device_size_bytes - 1; + _sfdp_info.smtbl._region_high_boundary[0] = _device_size_bytes - 1; - if ((hdr_info.smtbl.addr != 0) && (0 != hdr_info.smtbl.size)) { - tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", hdr_info.smtbl.addr, - hdr_info.smtbl.size); + if ((_sfdp_info.smtbl.addr != 0) && (0 != _sfdp_info.smtbl.size)) { + tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", _sfdp_info.smtbl.addr, + _sfdp_info.smtbl.size); if (_sfdp_parse_sector_map_table(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), - hdr_info.smtbl) < 0) { + _sfdp_info.smtbl) < 0) { tr_error("Init - Parse Sector Map Table Failed"); status = QSPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -412,9 +409,9 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) bool erase_failed = false; int status = QSPIF_BD_ERROR_OK; // Find region of erased address - int region = _utils_find_addr_region(addr); + int region = _utils_find_addr_region(addr, _sfdp_info.smtbl); // Erase Types of selected region - uint8_t bitfield = _region_erase_types_bitfield[region]; + uint8_t bitfield = _sfdp_info.smtbl._region_erase_types_bitfield[region]; tr_debug("Erase - addr: %llu, in_size: %llu", addr, in_size); @@ -434,9 +431,11 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) if (_legacy_erase_instruction == QSPI_NO_INST) { // Iterate to find next largest erase type that is a) supported by region, and b) smaller than size. // Find the matching instruction and erase size chunk for that type. - type = _utils_iterate_next_largest_erase_type(bitfield, size, (int)addr, _region_high_boundary[region]); - cur_erase_inst = _erase_type_inst_arr[type]; - eu_size = _erase_type_size_arr[type]; + type = _utils_iterate_next_largest_erase_type(bitfield, size, (int)addr, + region, + _sfdp_info.smtbl); + cur_erase_inst = _sfdp_info.smtbl._erase_type_inst_arr[type]; + eu_size = _sfdp_info.smtbl._erase_type_size_arr[type]; } else { // Must use legacy 4k erase instruction cur_erase_inst = _legacy_erase_instruction; @@ -469,10 +468,10 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) addr += chunk; size -= chunk; - if ((size > 0) && (addr > _region_high_boundary[region])) { + if ((size > 0) && (addr > _sfdp_info.smtbl._region_high_boundary[region])) { // erase crossed to next region region++; - bitfield = _region_erase_types_bitfield[region]; + bitfield = _sfdp_info.smtbl._region_erase_types_bitfield[region]; } if (false == _is_mem_ready()) { @@ -508,7 +507,7 @@ bd_size_t QSPIFBlockDevice::get_program_size() const bd_size_t QSPIFBlockDevice::get_erase_size() const { // return minimal erase size supported by all regions (0 if none exists) - return _min_common_erase_size; + return _sfdp_info.smtbl._min_common_erase_size; } const char *QSPIFBlockDevice::get_type() const @@ -525,10 +524,10 @@ bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr) } // Find region of current address - int region = _utils_find_addr_region(addr); + int region = _utils_find_addr_region(addr, _sfdp_info.smtbl); - int min_region_erase_size = _min_common_erase_size; - int8_t type_mask = ERASE_BITMASK_TYPE1; + int min_region_erase_size = _sfdp_info.smtbl._min_common_erase_size; + int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; int i_ind = 0; if (region != -1) { @@ -536,9 +535,9 @@ bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr) for (i_ind = 0; i_ind < 4; i_ind++) { // loop through erase types bitfield supported by region - if (_region_erase_types_bitfield[region] & type_mask) { + if (_sfdp_info.smtbl._region_erase_types_bitfield[region] & type_mask) { - min_region_erase_size = _erase_type_size_arr[i_ind]; + min_region_erase_size = _sfdp_info.smtbl._erase_type_size_arr[i_ind]; break; } type_mask = type_mask << 1; @@ -662,7 +661,7 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, s bool shouldSetQuadEnable = false; bool is_qpi_mode = false; - if (_sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size) != 0) { + if (_sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _sfdp_info.smtbl) != 0) { tr_error("Init - Detecting erase types instructions/sizes failed"); return -1; } @@ -846,7 +845,9 @@ int QSPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int return page_size; } -int QSPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size) +int QSPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, + int basic_param_table_size, + sfdp_smtbl_info &smtbl) { uint8_t bitfield = 0x01; @@ -854,23 +855,26 @@ int QSPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_para if (basic_param_table_size > QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE) { // Loop Erase Types 1-4 for (int i_ind = 0; i_ind < 4; i_ind++) { - _erase_type_inst_arr[i_ind] = QSPI_NO_INST; // Default for unsupported type - _erase_type_size_arr[i_ind] = 1 << basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]; // Size is 2^N where N is the table value - tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), _erase_type_inst_arr[i_ind], - _erase_type_size_arr[i_ind]); - if (_erase_type_size_arr[i_ind] > 1) { + smtbl._erase_type_inst_arr[i_ind] = QSPI_NO_INST; // Default for unsupported type + smtbl._erase_type_size_arr[i_ind] = 1 + << basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]; // Size is 2^N where N is the table value + tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smtbl._erase_type_inst_arr[i_ind], + smtbl._erase_type_size_arr[i_ind]); + if (smtbl._erase_type_size_arr[i_ind] > 1) { // if size==1 type is not supported - _erase_type_inst_arr[i_ind] = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE + 2 * i_ind]; + smtbl._erase_type_inst_arr[i_ind] = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE + + 2 * i_ind]; - if ((_erase_type_size_arr[i_ind] < _min_common_erase_size) || (_min_common_erase_size == 0)) { + if ((smtbl._erase_type_size_arr[i_ind] < smtbl._min_common_erase_size) + || (smtbl._min_common_erase_size == 0)) { //Set default minimal common erase for signal region - _min_common_erase_size = _erase_type_size_arr[i_ind]; + smtbl._min_common_erase_size = smtbl._erase_type_size_arr[i_ind]; } - _region_erase_types_bitfield[0] |= bitfield; // If there's no region map, set region "0" types bitfield as default + smtbl._region_erase_types_bitfield[0] |= bitfield; // If there's no region map, set region "0" types bitfield as default } - tr_debug("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), _erase_type_inst_arr[i_ind], - _erase_type_size_arr[i_ind]); + tr_debug("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smtbl._erase_type_inst_arr[i_ind], + smtbl._erase_type_size_arr[i_ind]); bitfield = bitfield << 1; } } else { @@ -1106,16 +1110,16 @@ int QSPIFBlockDevice::_sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param int QSPIFBlockDevice::_sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smtbl_info &smtbl) { - uint8_t sector_map_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 16 DWORDS = 64 Bytes */ + uint8_t sector_map_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */ uint32_t tmp_region_size = 0; int i_ind = 0; int prev_boundary = 0; // Default set to all type bits 1-4 are common - int min_common_erase_type_bits = ERASE_BITMASK_ALL; + int min_common_erase_type_bits = SFDP_ERASE_BITMASK_ALL; int status = sfdp_reader(smtbl.addr, sector_map_table, smtbl.size); if (status < 0) { - tr_error("Init - Read SFDP First Table Failed"); + tr_error("table retrieval failed"); return -1; } @@ -1125,29 +1129,30 @@ int QSPIFBlockDevice::_sfdp_parse_sector_map_table(Callback QSPIF_MAX_REGIONS) { + smtbl._regions_count = sector_map_table[2] + 1; + if (smtbl._regions_count > SFDP_SECTOR_MAP_MAX_REGIONS) { tr_error("Supporting up to %d regions, current setup to %d regions - fail", - QSPIF_MAX_REGIONS, _regions_count); + SFDP_SECTOR_MAP_MAX_REGIONS, + smtbl.regions_count); return -1; } // Loop through Regions and set for each one: size, supported erase types, high boundary offset // Calculate minimum Common Erase Type for all Regions - for (i_ind = 0; i_ind < _regions_count; i_ind++) { + for (i_ind = 0; i_ind < smtbl._regions_count; i_ind++) { tmp_region_size = ((*((uint32_t *)§or_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32 - _region_size_bytes[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes; - _region_erase_types_bitfield[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4 - min_common_erase_type_bits &= _region_erase_types_bitfield[i_ind]; - _region_high_boundary[i_ind] = (_region_size_bytes[i_ind] - 1) + prev_boundary; - prev_boundary = _region_high_boundary[i_ind] + 1; + smtbl._region_size_bytes[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes; + smtbl._region_erase_types_bitfield[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4 + min_common_erase_type_bits &= smtbl._region_erase_types_bitfield[i_ind]; + smtbl._region_high_boundary[i_ind] = (smtbl._region_size_bytes[i_ind] - 1) + prev_boundary; + prev_boundary = smtbl._region_high_boundary[i_ind] + 1; } // Calc minimum Common Erase Size from min_common_erase_type_bits - uint8_t type_mask = ERASE_BITMASK_TYPE1; + uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; for (i_ind = 0; i_ind < 4; i_ind++) { if (min_common_erase_type_bits & type_mask) { - _min_common_erase_size = _erase_type_size_arr[i_ind]; + smtbl._min_common_erase_size = smtbl._erase_type_size_arr[i_ind]; break; } type_mask = type_mask << 1; @@ -1155,7 +1160,7 @@ int QSPIFBlockDevice::_sfdp_parse_sector_map_table(Callback _device_size_bytes) || (_regions_count == 0)) { + if ((offset > _device_size_bytes) || (smtbl._regions_count == 0)) { return -1; } - if (_regions_count == 1) { + if (smtbl._regions_count == 1) { return 0; } - for (int i_ind = _regions_count - 2; i_ind >= 0; i_ind--) { + for (int i_ind = smtbl._regions_count - 2; i_ind >= 0; i_ind--) { - if (offset > _region_high_boundary[i_ind]) { + if (offset > smtbl._region_high_boundary[i_ind]) { return (i_ind + 1); } } @@ -1395,18 +1400,23 @@ int QSPIFBlockDevice::_utils_find_addr_region(bd_size_t offset) } -int QSPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry) +int QSPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, + int size, + int offset, + int region, + sfdp_smtbl_info &smtbl) { // Iterate on all supported Erase Types of the Region to which the offset belong to. // Iterates from highest type to lowest - uint8_t type_mask = ERASE_BITMASK_TYPE4; + uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE4; int i_ind = 0; int largest_erase_type = 0; for (i_ind = 3; i_ind >= 0; i_ind--) { if (bitfield & type_mask) { largest_erase_type = i_ind; - if ((size > (int)(_erase_type_size_arr[largest_erase_type])) && - ((boundry - offset) > (int)(_erase_type_size_arr[largest_erase_type]))) { + if ((size > (int)(smtbl._erase_type_size_arr[largest_erase_type])) && + ((_sfdp_info.smtbl._region_high_boundary[region] - offset) + > (int)(smtbl._erase_type_size_arr[largest_erase_type]))) { break; } else { bitfield &= ~type_mask; diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h index 2e41b9489b4..89316d420dd 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h @@ -70,8 +70,6 @@ enum qspif_polarity_mode { QSPIF_POLARITY_MODE_1 /* CPOL=1, CPHA=1 */ }; -#define QSPIF_MAX_REGIONS 10 -#define MAX_NUM_OF_ERASE_TYPES 4 #define QSPIF_MAX_ACTIVE_FLASH_DEVICES 10 /** BlockDevice for SFDP based flash devices over QSPI bus @@ -342,7 +340,9 @@ class QSPIFBlockDevice : public mbed::BlockDevice { 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); + int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, + int basic_param_table_size, + mbed::sfdp_smtbl_info &smtbl); // 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); @@ -354,11 +354,15 @@ class QSPIFBlockDevice : public mbed::BlockDevice { /* Utilities Functions */ /***********************/ // Find the region to which the given offset belong to - int _utils_find_addr_region(mbed::bd_size_t offset); + int _utils_find_addr_region(mbed::bd_size_t offset, mbed::sfdp_smtbl_info &smtbl); // Iterate on all supported Erase Types of the Region to which the offset belong to. // Iterates from highest type to lowest - int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry); + int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, + int size, + int offset, + int region, + mbed::sfdp_smtbl_info &smtbl); private: enum qspif_clear_protection_method_t { @@ -397,10 +401,6 @@ class QSPIFBlockDevice : public mbed::BlockDevice { // 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; @@ -410,13 +410,8 @@ class QSPIFBlockDevice : public mbed::BlockDevice { // 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 - bd_size_t _region_high_boundary[QSPIF_MAX_REGIONS]; //region high address offset boundary - //Each Region can support a bit combination of any of the 4 Erase Types - uint8_t _region_erase_types_bitfield[QSPIF_MAX_REGIONS]; - unsigned int _min_common_erase_size; // minimal common erase size for all regions (0 if none exists) + // 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; diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp index b10574ae5e4..d8c98cabc2f 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp @@ -65,12 +65,6 @@ using namespace mbed; #define SPIF_BASIC_PARAM_ERASE_TYPE_4_SIZE_BYTE 34 #define SPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1 -// Erase Types Per Region BitMask -#define ERASE_BITMASK_TYPE4 0x08 -#define ERASE_BITMASK_TYPE1 0x01 -#define ERASE_BITMASK_NONE 0x00 -#define ERASE_BITMASK_ALL 0x0F - #define IS_MEM_READY_MAX_RETRIES 10000 enum spif_default_instructions { @@ -115,7 +109,7 @@ SPIFBlockDevice::SPIFBlockDevice( _min_common_erase_size = 0; _regions_count = 1; - _region_erase_types_bitfield[0] = ERASE_BITMASK_NONE; + _region_erase_types_bitfield[0] = SFDP_ERASE_BITMASK_NONE; if (SPIF_BD_ERROR_OK != _spi_set_frequency(freq)) { tr_error("SPI Set Frequency Failed"); @@ -445,7 +439,7 @@ bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr) const int region = _utils_find_addr_region(addr); unsigned int min_region_erase_size = _min_common_erase_size; - int8_t type_mask = ERASE_BITMASK_TYPE1; + int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; int i_ind = 0; if (region != -1) { @@ -631,7 +625,7 @@ int SPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_addr int i_ind = 0; int prev_boundary = 0; // Default set to all type bits 1-4 are common - int min_common_erase_type_bits = ERASE_BITMASK_ALL; + int min_common_erase_type_bits = SFDP_ERASE_BITMASK_ALL; spif_bd_error status = _spi_send_read_command(SPIF_SFDP, sector_map_table, sector_map_table_addr /*address*/, @@ -666,7 +660,7 @@ int SPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_addr } // Calc minimum Common Erase Size from min_common_erase_type_bits - uint8_t type_mask = ERASE_BITMASK_TYPE1; + uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; for (i_ind = 0; i_ind < 4; i_ind++) { if (min_common_erase_type_bits & type_mask) { _min_common_erase_size = _erase_type_size_arr[i_ind]; @@ -943,7 +937,7 @@ int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, i { // Iterate on all supported Erase Types of the Region to which the offset belong to. // Iterates from highest type to lowest - uint8_t type_mask = ERASE_BITMASK_TYPE4; + uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE4; int i_ind = 0; int largest_erase_type = 0; for (i_ind = 3; i_ind >= 0; i_ind--) { diff --git a/drivers/internal/SFDP.h b/drivers/internal/SFDP.h index 9951df792fd..23bbdcae96b 100644 --- a/drivers/internal/SFDP.h +++ b/drivers/internal/SFDP.h @@ -27,6 +27,15 @@ namespace mbed { static const int SFDP_HEADER_SIZE = 8; ///< Size of an SFDP header */ static const int SFDP_BASIC_PARAMS_TBL_SIZE = 80; ///< Basic Parameter Table size in Bytes, 20 DWORDS */ +static const int SFDP_SECTOR_MAP_MAX_REGIONS = 10; + +// Erase Types Per Region BitMask +static const int SFDP_ERASE_BITMASK_TYPE4 = 0x08; +static const int SFDP_ERASE_BITMASK_TYPE1 = 0x01; +static const int SFDP_ERASE_BITMASK_NONE = 0x00; +static const int SFDP_ERASE_BITMASK_ALL = 0x0F; + +static const int SFDP_MAX_NUM_OF_ERASE_TYPES = 4; /** SFDP Basic Parameter Table info */ struct sfdp_bptbl_info { @@ -38,6 +47,15 @@ struct sfdp_bptbl_info { struct sfdp_smtbl_info { uint32_t addr; size_t size; + int _regions_count; + int _region_size_bytes[SFDP_SECTOR_MAP_MAX_REGIONS]; + //Each Region can support a bit combination of any of the 4 Erase Types + uint8_t _region_erase_types_bitfield[SFDP_SECTOR_MAP_MAX_REGIONS]; + unsigned int _min_common_erase_size; // minimal common erase size for all regions (0 if none exists) + bd_size_t _region_high_boundary[SFDP_SECTOR_MAP_MAX_REGIONS]; //region high address offset boundary + // Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size) + int _erase_type_inst_arr[SFDP_MAX_NUM_OF_ERASE_TYPES]; + unsigned int _erase_type_size_arr[SFDP_MAX_NUM_OF_ERASE_TYPES]; }; /** SFDP Parameter Table addresses and sizes */ @@ -90,5 +108,7 @@ int sfdp_parse_single_param_header(sfdp_prm_hdr *parameter_header, sfdp_hdr_info */ int sfdp_parse_headers(Callback sfdp_reader, sfdp_hdr_info &hdr_info); +int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smtbl_info &smtbl); + } /* namespace mbed */ #endif diff --git a/drivers/source/SFDP.cpp b/drivers/source/SFDP.cpp index f4f29f738a7..af8afa2b91d 100644 --- a/drivers/source/SFDP.cpp +++ b/drivers/source/SFDP.cpp @@ -134,5 +134,10 @@ int sfdp_parse_headers(Callback sfdp_reader, return 0; } +int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smtbl_info &smtbl) +{ + return 0; +} + } /* namespace mbed */ #endif /* (DEVICE_SPI || DEVICE_QSPI) */ From 7518a35da30e1f8c985408a186b6f19016ac3b3e Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Wed, 22 Jan 2020 10:39:41 +0200 Subject: [PATCH 05/12] SFDP: data structures got refactored --- .../COMPONENT_QSPIF/QSPIFBlockDevice.cpp | 92 +++++++++---------- .../COMPONENT_QSPIF/QSPIFBlockDevice.h | 2 +- drivers/internal/SFDP.h | 24 +++-- drivers/source/SFDP.cpp | 2 +- 4 files changed, 64 insertions(+), 56 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index 1e04235cc03..6f123c89286 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -152,9 +152,9 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam } // Initialize parameters - _sfdp_info.smtbl._min_common_erase_size = 0; - _sfdp_info.smtbl._regions_count = 1; - _sfdp_info.smtbl._region_erase_types_bitfield[0] = SFDP_ERASE_BITMASK_NONE; + _sfdp_info.smtbl.regions_min_common_erase_size = 0; + _sfdp_info.smtbl.region_cnt = 1; + _sfdp_info.smtbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE; // Until proven otherwise, assume no quad enable _quad_enable_register_idx = QSPIF_NO_QUAD_ENABLE; @@ -259,9 +259,9 @@ int QSPIFBlockDevice::init() } /**************************** Parse Sector Map Table ***********************************/ - _sfdp_info.smtbl._region_size_bytes[0] = + _sfdp_info.smtbl.region_size[0] = _device_size_bytes; // If there's no region map, we have a single region sized the entire device size - _sfdp_info.smtbl._region_high_boundary[0] = _device_size_bytes - 1; + _sfdp_info.smtbl.region_high_boundary[0] = _device_size_bytes - 1; if ((_sfdp_info.smtbl.addr != 0) && (0 != _sfdp_info.smtbl.size)) { tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", _sfdp_info.smtbl.addr, @@ -411,7 +411,7 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) // Find region of erased address int region = _utils_find_addr_region(addr, _sfdp_info.smtbl); // Erase Types of selected region - uint8_t bitfield = _sfdp_info.smtbl._region_erase_types_bitfield[region]; + uint8_t bitfield = _sfdp_info.smtbl.region_erase_types_bitfld[region]; tr_debug("Erase - addr: %llu, in_size: %llu", addr, in_size); @@ -434,8 +434,8 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) type = _utils_iterate_next_largest_erase_type(bitfield, size, (int)addr, region, _sfdp_info.smtbl); - cur_erase_inst = _sfdp_info.smtbl._erase_type_inst_arr[type]; - eu_size = _sfdp_info.smtbl._erase_type_size_arr[type]; + cur_erase_inst = _sfdp_info.smtbl.erase_type_inst_arr[type]; + eu_size = _sfdp_info.smtbl.erase_type_size_arr[type]; } else { // Must use legacy 4k erase instruction cur_erase_inst = _legacy_erase_instruction; @@ -468,10 +468,10 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) addr += chunk; size -= chunk; - if ((size > 0) && (addr > _sfdp_info.smtbl._region_high_boundary[region])) { + if ((size > 0) && (addr > _sfdp_info.smtbl.region_high_boundary[region])) { // erase crossed to next region region++; - bitfield = _sfdp_info.smtbl._region_erase_types_bitfield[region]; + bitfield = _sfdp_info.smtbl.region_erase_types_bitfld[region]; } if (false == _is_mem_ready()) { @@ -507,7 +507,7 @@ bd_size_t QSPIFBlockDevice::get_program_size() const bd_size_t QSPIFBlockDevice::get_erase_size() const { // return minimal erase size supported by all regions (0 if none exists) - return _sfdp_info.smtbl._min_common_erase_size; + return _sfdp_info.smtbl.regions_min_common_erase_size; } const char *QSPIFBlockDevice::get_type() const @@ -526,7 +526,7 @@ bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr) // Find region of current address int region = _utils_find_addr_region(addr, _sfdp_info.smtbl); - int min_region_erase_size = _sfdp_info.smtbl._min_common_erase_size; + int min_region_erase_size = _sfdp_info.smtbl.regions_min_common_erase_size; int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; int i_ind = 0; @@ -535,9 +535,9 @@ bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr) for (i_ind = 0; i_ind < 4; i_ind++) { // loop through erase types bitfield supported by region - if (_sfdp_info.smtbl._region_erase_types_bitfield[region] & type_mask) { + if (_sfdp_info.smtbl.region_erase_types_bitfld[region] & type_mask) { - min_region_erase_size = _sfdp_info.smtbl._erase_type_size_arr[i_ind]; + min_region_erase_size = _sfdp_info.smtbl.erase_type_size_arr[i_ind]; break; } type_mask = type_mask << 1; @@ -855,26 +855,26 @@ int QSPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_para if (basic_param_table_size > QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE) { // Loop Erase Types 1-4 for (int i_ind = 0; i_ind < 4; i_ind++) { - smtbl._erase_type_inst_arr[i_ind] = QSPI_NO_INST; // Default for unsupported type - smtbl._erase_type_size_arr[i_ind] = 1 - << basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]; // Size is 2^N where N is the table value - tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smtbl._erase_type_inst_arr[i_ind], - smtbl._erase_type_size_arr[i_ind]); - if (smtbl._erase_type_size_arr[i_ind] > 1) { + smtbl.erase_type_inst_arr[i_ind] = QSPI_NO_INST; // Default for unsupported type + smtbl.erase_type_size_arr[i_ind] = 1 + << basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]; // Size is 2^N where N is the table value + tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smtbl.erase_type_inst_arr[i_ind], + smtbl.erase_type_size_arr[i_ind]); + if (smtbl.erase_type_size_arr[i_ind] > 1) { // if size==1 type is not supported - smtbl._erase_type_inst_arr[i_ind] = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE - + 2 * i_ind]; + smtbl.erase_type_inst_arr[i_ind] = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE + + 2 * i_ind]; - if ((smtbl._erase_type_size_arr[i_ind] < smtbl._min_common_erase_size) - || (smtbl._min_common_erase_size == 0)) { + if ((smtbl.erase_type_size_arr[i_ind] < smtbl.regions_min_common_erase_size) + || (smtbl.regions_min_common_erase_size == 0)) { //Set default minimal common erase for signal region - smtbl._min_common_erase_size = smtbl._erase_type_size_arr[i_ind]; + smtbl.regions_min_common_erase_size = smtbl.erase_type_size_arr[i_ind]; } - smtbl._region_erase_types_bitfield[0] |= bitfield; // If there's no region map, set region "0" types bitfield as default + smtbl.region_erase_types_bitfld[0] |= bitfield; // If there's no region map, set region "0" types bitfield as default } - tr_debug("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smtbl._erase_type_inst_arr[i_ind], - smtbl._erase_type_size_arr[i_ind]); + tr_debug("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smtbl.erase_type_inst_arr[i_ind], + smtbl.erase_type_size_arr[i_ind]); bitfield = bitfield << 1; } } else { @@ -1107,7 +1107,7 @@ int QSPIFBlockDevice::_sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param return status; } -int QSPIFBlockDevice::_sfdp_parse_sector_map_table(Callback sfdp_reader, +int QSPIFBlockDevice::_sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smtbl_info &smtbl) { uint8_t sector_map_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */ @@ -1129,8 +1129,8 @@ int QSPIFBlockDevice::_sfdp_parse_sector_map_table(Callback SFDP_SECTOR_MAP_MAX_REGIONS) { + smtbl.region_cnt = sector_map_table[2] + 1; + if (smtbl.region_cnt > SFDP_SECTOR_MAP_MAX_REGIONS) { tr_error("Supporting up to %d regions, current setup to %d regions - fail", SFDP_SECTOR_MAP_MAX_REGIONS, smtbl.regions_count); @@ -1139,20 +1139,20 @@ int QSPIFBlockDevice::_sfdp_parse_sector_map_table(Callback> 8) & 0x00FFFFFF; // bits 9-32 - smtbl._region_size_bytes[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes; - smtbl._region_erase_types_bitfield[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4 - min_common_erase_type_bits &= smtbl._region_erase_types_bitfield[i_ind]; - smtbl._region_high_boundary[i_ind] = (smtbl._region_size_bytes[i_ind] - 1) + prev_boundary; - prev_boundary = smtbl._region_high_boundary[i_ind] + 1; + smtbl.region_size[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes; + smtbl.region_erase_types_bitfld[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4 + min_common_erase_type_bits &= smtbl.region_erase_types_bitfld[i_ind]; + smtbl.region_high_boundary[i_ind] = (smtbl.region_size[i_ind] - 1) + prev_boundary; + prev_boundary = smtbl.region_high_boundary[i_ind] + 1; } // Calc minimum Common Erase Size from min_common_erase_type_bits uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; for (i_ind = 0; i_ind < 4; i_ind++) { if (min_common_erase_type_bits & type_mask) { - smtbl._min_common_erase_size = smtbl._erase_type_size_arr[i_ind]; + smtbl.regions_min_common_erase_size = smtbl.erase_type_size_arr[i_ind]; break; } type_mask = type_mask << 1; @@ -1160,7 +1160,7 @@ int QSPIFBlockDevice::_sfdp_parse_sector_map_table(Callback _device_size_bytes) || (smtbl._regions_count == 0)) { + if ((offset > _device_size_bytes) || (smtbl.region_cnt == 0)) { return -1; } - if (smtbl._regions_count == 1) { + if (smtbl.region_cnt == 1) { return 0; } - for (int i_ind = smtbl._regions_count - 2; i_ind >= 0; i_ind--) { + for (int i_ind = smtbl.region_cnt - 2; i_ind >= 0; i_ind--) { - if (offset > smtbl._region_high_boundary[i_ind]) { + if (offset > smtbl.region_high_boundary[i_ind]) { return (i_ind + 1); } } @@ -1414,9 +1414,9 @@ int QSPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, for (i_ind = 3; i_ind >= 0; i_ind--) { if (bitfield & type_mask) { largest_erase_type = i_ind; - if ((size > (int)(smtbl._erase_type_size_arr[largest_erase_type])) && - ((_sfdp_info.smtbl._region_high_boundary[region] - offset) - > (int)(smtbl._erase_type_size_arr[largest_erase_type]))) { + if ((size > (int)(smtbl.erase_type_size_arr[largest_erase_type])) && + ((_sfdp_info.smtbl.region_high_boundary[region] - offset) + > (int)(smtbl.erase_type_size_arr[largest_erase_type]))) { break; } else { bitfield &= ~type_mask; diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h index 89316d420dd..14e02793ef2 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h @@ -320,7 +320,7 @@ class QSPIFBlockDevice : public mbed::BlockDevice { int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size); // Parse and read information required by Regions Sector Map - int _sfdp_parse_sector_map_table(mbed::Callback sfdp_reader, + int _sfdp_parse_sector_map_table(mbed::Callback sfdp_reader, mbed::sfdp_smtbl_info &smtbl); // Detect the soft reset protocol and reset - returns error if soft reset is not supported diff --git a/drivers/internal/SFDP.h b/drivers/internal/SFDP.h index 23bbdcae96b..32e9cc4646d 100644 --- a/drivers/internal/SFDP.h +++ b/drivers/internal/SFDP.h @@ -47,15 +47,15 @@ struct sfdp_bptbl_info { struct sfdp_smtbl_info { uint32_t addr; size_t size; - int _regions_count; - int _region_size_bytes[SFDP_SECTOR_MAP_MAX_REGIONS]; + int region_cnt; + int region_size[SFDP_SECTOR_MAP_MAX_REGIONS]; // [Bytes] //Each Region can support a bit combination of any of the 4 Erase Types - uint8_t _region_erase_types_bitfield[SFDP_SECTOR_MAP_MAX_REGIONS]; - unsigned int _min_common_erase_size; // minimal common erase size for all regions (0 if none exists) - bd_size_t _region_high_boundary[SFDP_SECTOR_MAP_MAX_REGIONS]; //region high address offset boundary + uint8_t region_erase_types_bitfld[SFDP_SECTOR_MAP_MAX_REGIONS]; + unsigned int regions_min_common_erase_size; // minimal common erase size for all regions (0 if none exists) + bd_size_t region_high_boundary[SFDP_SECTOR_MAP_MAX_REGIONS]; //region high address offset boundary // Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size) - int _erase_type_inst_arr[SFDP_MAX_NUM_OF_ERASE_TYPES]; - unsigned int _erase_type_size_arr[SFDP_MAX_NUM_OF_ERASE_TYPES]; + int erase_type_inst_arr[SFDP_MAX_NUM_OF_ERASE_TYPES]; + unsigned int erase_type_size_arr[SFDP_MAX_NUM_OF_ERASE_TYPES]; }; /** SFDP Parameter Table addresses and sizes */ @@ -108,7 +108,15 @@ int sfdp_parse_single_param_header(sfdp_prm_hdr *parameter_header, sfdp_hdr_info */ int sfdp_parse_headers(Callback sfdp_reader, sfdp_hdr_info &hdr_info); -int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smtbl_info &smtbl); +/** Parse Sector Map Parameter Table + * Retrieves the table from a device and parses the information contained by the table + * + * @param sfdp_reader Callback function used to read headers from a device + * @param smtbl All information parsed from the table gets passed back on this structure + * + * @return 0 on success, negative error code on failure + */ +int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smtbl_info &smtbl); } /* namespace mbed */ #endif diff --git a/drivers/source/SFDP.cpp b/drivers/source/SFDP.cpp index af8afa2b91d..ae1fecc9508 100644 --- a/drivers/source/SFDP.cpp +++ b/drivers/source/SFDP.cpp @@ -134,7 +134,7 @@ int sfdp_parse_headers(Callback sfdp_reader, return 0; } -int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smtbl_info &smtbl) +int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smtbl_info &smtbl) { return 0; } From 83c0fdf19fec4fe5da594033f2b2876293c5c41f Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Wed, 22 Jan 2020 10:55:52 +0200 Subject: [PATCH 06/12] QSPIFBlockDevice: Sector Map Table parsing moved under SFDP --- .../COMPONENT_QSPIF/QSPIFBlockDevice.cpp | 63 +------------------ .../COMPONENT_QSPIF/QSPIFBlockDevice.h | 4 -- drivers/source/SFDP.cpp | 53 ++++++++++++++++ 3 files changed, 55 insertions(+), 65 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index 6f123c89286..9d85db42b90 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -266,8 +266,8 @@ int QSPIFBlockDevice::init() if ((_sfdp_info.smtbl.addr != 0) && (0 != _sfdp_info.smtbl.size)) { tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", _sfdp_info.smtbl.addr, _sfdp_info.smtbl.size); - if (_sfdp_parse_sector_map_table(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), - _sfdp_info.smtbl) < 0) { + if (sfdp_parse_sector_map_table(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), + _sfdp_info.smtbl) < 0) { tr_error("Init - Parse Sector Map Table Failed"); status = QSPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -1107,65 +1107,6 @@ int QSPIFBlockDevice::_sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param return status; } -int QSPIFBlockDevice::_sfdp_parse_sector_map_table(Callback sfdp_reader, - sfdp_smtbl_info &smtbl) -{ - uint8_t sector_map_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */ - uint32_t tmp_region_size = 0; - int i_ind = 0; - int prev_boundary = 0; - // Default set to all type bits 1-4 are common - int min_common_erase_type_bits = SFDP_ERASE_BITMASK_ALL; - - int status = sfdp_reader(smtbl.addr, sector_map_table, smtbl.size); - if (status < 0) { - tr_error("table retrieval failed"); - return -1; - } - - // Currently we support only Single Map Descriptor - if (!((sector_map_table[0] & 0x3) == 0x03) && (sector_map_table[1] == 0x0)) { - tr_error("Sector Map - Supporting Only Single! Map Descriptor (not map commands)"); - return -1; - } - - smtbl.region_cnt = sector_map_table[2] + 1; - if (smtbl.region_cnt > SFDP_SECTOR_MAP_MAX_REGIONS) { - tr_error("Supporting up to %d regions, current setup to %d regions - fail", - SFDP_SECTOR_MAP_MAX_REGIONS, - smtbl.regions_count); - return -1; - } - - // Loop through Regions and set for each one: size, supported erase types, high boundary offset - // Calculate minimum Common Erase Type for all Regions - for (i_ind = 0; i_ind < smtbl.region_cnt; i_ind++) { - tmp_region_size = ((*((uint32_t *)§or_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32 - smtbl.region_size[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes; - smtbl.region_erase_types_bitfld[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4 - min_common_erase_type_bits &= smtbl.region_erase_types_bitfld[i_ind]; - smtbl.region_high_boundary[i_ind] = (smtbl.region_size[i_ind] - 1) + prev_boundary; - prev_boundary = smtbl.region_high_boundary[i_ind] + 1; - } - - // Calc minimum Common Erase Size from min_common_erase_type_bits - uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; - for (i_ind = 0; i_ind < 4; i_ind++) { - if (min_common_erase_type_bits & type_mask) { - smtbl.regions_min_common_erase_size = smtbl.erase_type_size_arr[i_ind]; - break; - } - type_mask = type_mask << 1; - } - - if (i_ind == 4) { - // No common erase type was found between regions - smtbl.regions_min_common_erase_size = 0; - } - - return 0; -} - int QSPIFBlockDevice::_handle_vendor_quirks() { uint8_t vendor_device_ids[QSPI_RDID_DATA_LENGTH] = {0}; diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h index 14e02793ef2..36bdbefa584 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h @@ -319,10 +319,6 @@ class QSPIFBlockDevice : public mbed::BlockDevice { // 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 Sector Map - int _sfdp_parse_sector_map_table(mbed::Callback sfdp_reader, - mbed::sfdp_smtbl_info &smtbl); - // 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); diff --git a/drivers/source/SFDP.cpp b/drivers/source/SFDP.cpp index ae1fecc9508..ef909f9f870 100644 --- a/drivers/source/SFDP.cpp +++ b/drivers/source/SFDP.cpp @@ -136,6 +136,59 @@ int sfdp_parse_headers(Callback sfdp_reader, int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smtbl_info &smtbl) { + uint8_t sector_map_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */ + uint32_t tmp_region_size = 0; + int i_ind = 0; + int prev_boundary = 0; + // Default set to all type bits 1-4 are common + int min_common_erase_type_bits = SFDP_ERASE_BITMASK_ALL; + + int status = sfdp_reader(smtbl.addr, sector_map_table, smtbl.size); + if (status < 0) { + tr_error("table retrieval failed"); + return -1; + } + + // Currently we support only Single Map Descriptor + if (!((sector_map_table[0] & 0x3) == 0x03) && (sector_map_table[1] == 0x0)) { + tr_error("Sector Map - Supporting Only Single! Map Descriptor (not map commands)"); + return -1; + } + + smtbl.region_cnt = sector_map_table[2] + 1; + if (smtbl.region_cnt > SFDP_SECTOR_MAP_MAX_REGIONS) { + tr_error("Supporting up to %d regions, current setup to %d regions - fail", + SFDP_SECTOR_MAP_MAX_REGIONS, + smtbl.region_cnt); + return -1; + } + + // Loop through Regions and set for each one: size, supported erase types, high boundary offset + // Calculate minimum Common Erase Type for all Regions + for (i_ind = 0; i_ind < smtbl.region_cnt; i_ind++) { + tmp_region_size = ((*((uint32_t *)§or_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32 + smtbl.region_size[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes; + smtbl.region_erase_types_bitfld[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4 + min_common_erase_type_bits &= smtbl.region_erase_types_bitfld[i_ind]; + smtbl.region_high_boundary[i_ind] = (smtbl.region_size[i_ind] - 1) + prev_boundary; + prev_boundary = smtbl.region_high_boundary[i_ind] + 1; + } + + // Calc minimum Common Erase Size from min_common_erase_type_bits + uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; + for (i_ind = 0; i_ind < 4; i_ind++) { + if (min_common_erase_type_bits & type_mask) { + smtbl.regions_min_common_erase_size = smtbl.erase_type_size_arr[i_ind]; + break; + } + type_mask = type_mask << 1; + } + + if (i_ind == 4) { + // No common erase type was found between regions + smtbl.regions_min_common_erase_size = 0; + } + return 0; } From 57722666a180afd97cf0a0ec7421946ba8251fd8 Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Wed, 22 Jan 2020 13:43:04 +0200 Subject: [PATCH 07/12] SPIFBlockDevice: Consolidates SFDP info data This far all SFDP Sector Map Table related data has been found in small pieces inside SPIFBlockDevice. Purpose was to consolidate the data under one SFDP structure where all the information gathered from SFDP tables is stored. More generic version of a function used for parsing a Sector Map Table was taken into use to avoid duplicate code. The implementation taken into use is the one which got split from QSPIFBlockDevice and resides now under the SFDP module. --- .../COMPONENT_SPIF/SPIFBlockDevice.cpp | 158 ++++++------------ .../COMPONENT_SPIF/SPIFBlockDevice.h | 38 ++--- drivers/internal/SFDP.h | 2 + 3 files changed, 68 insertions(+), 130 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp index d8c98cabc2f..ec8493534f1 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp @@ -107,9 +107,9 @@ SPIFBlockDevice::SPIFBlockDevice( _write_dummy_and_mode_cycles = 0; _dummy_and_mode_cycles = _read_dummy_and_mode_cycles; - _min_common_erase_size = 0; - _regions_count = 1; - _region_erase_types_bitfield[0] = SFDP_ERASE_BITMASK_NONE; + _sfdp_info.smtbl.regions_min_common_erase_size = 0; + _sfdp_info.smtbl.region_cnt = 1; + _sfdp_info.smtbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE; if (SPIF_BD_ERROR_OK != _spi_set_frequency(freq)) { tr_error("SPI Set Frequency Failed"); @@ -190,14 +190,15 @@ int SPIFBlockDevice::init() } /**************************** Parse Sector Map Table ***********************************/ - _region_size_bytes[0] = + _sfdp_info.smtbl.region_size[0] = _device_size_bytes; // If there's no region map, we have a single region sized the entire device size - _region_high_boundary[0] = _device_size_bytes - 1; + _sfdp_info.smtbl.region_high_boundary[0] = _device_size_bytes - 1; if ((hdr_info.smtbl.addr != 0) && (0 != hdr_info.smtbl.size)) { tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", hdr_info.smtbl.addr, hdr_info.smtbl.size); - if (0 != _sfdp_parse_sector_map_table(hdr_info.smtbl.addr, hdr_info.smtbl.size)) { + if (sfdp_parse_sector_map_table(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), + _sfdp_info.smtbl) < 0) { tr_error("init - Parse Sector Map Table Failed"); status = SPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -341,13 +342,13 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) bool erase_failed = false; int status = SPIF_BD_ERROR_OK; // Find region of erased address - int region = _utils_find_addr_region(addr); + int region = _utils_find_addr_region(addr, _sfdp_info.smtbl); if (region < 0) { tr_error("no region found for address %llu", addr); return SPIF_BD_ERROR_INVALID_ERASE_PARAMS; } // Erase Types of selected region - uint8_t bitfield = _region_erase_types_bitfield[region]; + uint8_t bitfield = _sfdp_info.smtbl.region_erase_types_bitfld[region]; tr_debug("erase - addr: %llu, in_size: %llu", addr, in_size); @@ -366,10 +367,11 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) // iterate to find next Largest erase type ( a. supported by region, b. smaller than size) // find the matching instruction and erase size chunk for that type. - type = _utils_iterate_next_largest_erase_type(bitfield, size, (unsigned int)addr, _region_high_boundary[region]); - cur_erase_inst = _erase_type_inst_arr[type]; - offset = addr % _erase_type_size_arr[type]; - chunk = ((offset + size) < _erase_type_size_arr[type]) ? size : (_erase_type_size_arr[type] - offset); + type = _utils_iterate_next_largest_erase_type(bitfield, size, (unsigned int)addr, region, _sfdp_info.smtbl); + cur_erase_inst = _sfdp_info.smtbl.erase_type_inst_arr[type]; + offset = addr % _sfdp_info.smtbl.erase_type_size_arr[type]; + chunk = ((offset + size) < _sfdp_info.smtbl.erase_type_size_arr[type]) ? + size : (_sfdp_info.smtbl.erase_type_size_arr[type] - offset); tr_debug("erase - addr: %llu, size:%d, Inst: 0x%xh, chunk: %" PRIu32 " , ", addr, size, cur_erase_inst, chunk); @@ -390,10 +392,10 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) addr += chunk; size -= chunk; - if ((size > 0) && (addr > _region_high_boundary[region])) { + if ((size > 0) && (addr > _sfdp_info.smtbl.region_high_boundary[region])) { // erase crossed to next region region++; - bitfield = _region_erase_types_bitfield[region]; + bitfield = _sfdp_info.smtbl.region_erase_types_bitfld[region]; } if (false == _is_mem_ready()) { @@ -429,16 +431,16 @@ bd_size_t SPIFBlockDevice::get_program_size() const bd_size_t SPIFBlockDevice::get_erase_size() const { // return minimal erase size supported by all regions (0 if none exists) - return _min_common_erase_size; + return _sfdp_info.smtbl.regions_min_common_erase_size; } // Find minimal erase size supported by the region to which the address belongs to bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr) const { // Find region of current address - int region = _utils_find_addr_region(addr); + int region = _utils_find_addr_region(addr, _sfdp_info.smtbl); - unsigned int min_region_erase_size = _min_common_erase_size; + unsigned int min_region_erase_size = _sfdp_info.smtbl.regions_min_common_erase_size; int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; int i_ind = 0; @@ -447,9 +449,9 @@ bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr) const for (i_ind = 0; i_ind < 4; i_ind++) { // loop through erase types bitfield supported by region - if (_region_erase_types_bitfield[region] & type_mask) { + if (_sfdp_info.smtbl.region_erase_types_bitfld[region] & type_mask) { - min_region_erase_size = _erase_type_size_arr[i_ind]; + min_region_erase_size = _sfdp_info.smtbl.erase_type_size_arr[i_ind]; break; } type_mask = type_mask << 1; @@ -618,65 +620,6 @@ spif_bd_error SPIFBlockDevice::_spi_send_general_command(int instruction, bd_add /*********************************************************/ /********** SFDP Parsing and Detection Functions *********/ /*********************************************************/ -int SPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size) -{ - uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */ - uint32_t tmp_region_size = 0; - int i_ind = 0; - int prev_boundary = 0; - // Default set to all type bits 1-4 are common - int min_common_erase_type_bits = SFDP_ERASE_BITMASK_ALL; - - - spif_bd_error status = _spi_send_read_command(SPIF_SFDP, sector_map_table, sector_map_table_addr /*address*/, - sector_map_table_size); - if (status != SPIF_BD_ERROR_OK) { - tr_error("init - Read SFDP First Table Failed"); - return -1; - } - - // Currently we support only Single Map Descriptor - if (!((sector_map_table[0] & 0x3) == 0x03) && (sector_map_table[1] == 0x0)) { - tr_error("Sector Map - Supporting Only Single! Map Descriptor (not map commands)"); - return -1; - } - - _regions_count = sector_map_table[2] + 1; - if (_regions_count > SPIF_MAX_REGIONS) { - tr_error("Supporting up to %d regions, current setup to %d regions - fail", - SPIF_MAX_REGIONS, _regions_count); - return -1; - } - - // Loop through Regions and set for each one: size, supported erase types, high boundary offset - // Calculate minimum Common Erase Type for all Regions - for (i_ind = 0; i_ind < _regions_count; i_ind++) { - tmp_region_size = ((*((uint32_t *)§or_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32 - _region_size_bytes[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes; - _region_erase_types_bitfield[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4 - min_common_erase_type_bits &= _region_erase_types_bitfield[i_ind]; - _region_high_boundary[i_ind] = (_region_size_bytes[i_ind] - 1) + prev_boundary; - prev_boundary = _region_high_boundary[i_ind] + 1; - } - - // Calc minimum Common Erase Size from min_common_erase_type_bits - uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; - for (i_ind = 0; i_ind < 4; i_ind++) { - if (min_common_erase_type_bits & type_mask) { - _min_common_erase_size = _erase_type_size_arr[i_ind]; - break; - } - type_mask = type_mask << 1; - } - - if (i_ind == 4) { - // No common erase type was found between regions - _min_common_erase_size = 0; - } - - return 0; -} - int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size) { uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */ @@ -713,8 +656,7 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, si _page_size_bytes = _sfdp_detect_page_size(param_table, basic_table_size); // Detect and Set Erase Types - _sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _erase4k_inst, _erase_type_inst_arr, - _erase_type_size_arr); + _sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _erase4k_inst, _sfdp_info.smtbl); _erase_instruction = _erase4k_inst; // Detect and Set fastest Bus mode (default 1-1-1) @@ -745,7 +687,7 @@ unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &erase4k_inst, - int *erase_type_inst_arr, unsigned int *erase_type_size_arr) + sfdp_smtbl_info &smtbl) { erase4k_inst = 0xff; bool found_4Kerase_type = false; @@ -757,34 +699,36 @@ int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param if (basic_param_table_size > SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE) { // Loop Erase Types 1-4 for (int i_ind = 0; i_ind < 4; i_ind++) { - erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type - erase_type_size_arr[i_ind] = local_math_power(2, - basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N - tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), erase_type_inst_arr[i_ind], - erase_type_size_arr[i_ind]); - if (erase_type_size_arr[i_ind] > 1) { + smtbl.erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type + smtbl.erase_type_size_arr[i_ind] = local_math_power( + 2, basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N + tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smtbl.erase_type_inst_arr[i_ind], + smtbl.erase_type_size_arr[i_ind]); + if (smtbl.erase_type_size_arr[i_ind] > 1) { // if size==1 type is not supported - erase_type_inst_arr[i_ind] = basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind]; + smtbl.erase_type_inst_arr[i_ind] = + basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind]; - if ((erase_type_size_arr[i_ind] < _min_common_erase_size) || (_min_common_erase_size == 0)) { + if ((smtbl.erase_type_size_arr[i_ind] < smtbl.regions_min_common_erase_size) + || (smtbl.regions_min_common_erase_size == 0)) { //Set default minimal common erase for singal region - _min_common_erase_size = erase_type_size_arr[i_ind]; + smtbl.regions_min_common_erase_size = smtbl.erase_type_size_arr[i_ind]; } // SFDP standard requires 4K Erase type to exist and its instruction to be identical to legacy field erase instruction - if (erase_type_size_arr[i_ind] == 4096) { + if (smtbl.erase_type_size_arr[i_ind] == 4096) { found_4Kerase_type = true; - if (erase4k_inst != erase_type_inst_arr[i_ind]) { + if (erase4k_inst != smtbl.erase_type_inst_arr[i_ind]) { //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table - erase4k_inst = erase_type_inst_arr[i_ind]; + erase4k_inst = smtbl.erase_type_inst_arr[i_ind]; tr_warning("_detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K"); } } - _region_erase_types_bitfield[0] |= bitfield; // If there's no region map, set region "0" types bitfield as defualt; + smtbl.region_erase_types_bitfld[0] |= bitfield; // no region map, set region "0" types bitfield as default } tr_info("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), - erase_type_inst_arr[i_ind], erase_type_size_arr[i_ind]); + smtbl.erase_type_inst_arr[i_ind], smtbl.erase_type_size_arr[i_ind]); bitfield = bitfield << 1; } } @@ -912,20 +856,20 @@ int SPIFBlockDevice::_set_write_enable() /*********************************************/ /************* Utility Functions *************/ /*********************************************/ -int SPIFBlockDevice::_utils_find_addr_region(bd_size_t offset) const +int SPIFBlockDevice::_utils_find_addr_region(bd_size_t offset, const sfdp_smtbl_info &smtbl) const { //Find the region to which the given offset belong to - if ((offset > _device_size_bytes) || (_regions_count == 0)) { + if ((offset > _device_size_bytes) || (smtbl.region_cnt == 0)) { return -1; } - if (_regions_count == 1) { + if (smtbl.region_cnt == 1) { return 0; } - for (int i_ind = _regions_count - 2; i_ind >= 0; i_ind--) { + for (int i_ind = smtbl.region_cnt - 2; i_ind >= 0; i_ind--) { - if (offset > _region_high_boundary[i_ind]) { + if (offset > smtbl.region_high_boundary[i_ind]) { return (i_ind + 1); } } @@ -933,7 +877,11 @@ int SPIFBlockDevice::_utils_find_addr_region(bd_size_t offset) const } -int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry) +int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, + int size, + int offset, + int region, + sfdp_smtbl_info &smtbl) { // Iterate on all supported Erase Types of the Region to which the offset belong to. // Iterates from highest type to lowest @@ -943,8 +891,9 @@ int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, i for (i_ind = 3; i_ind >= 0; i_ind--) { if (bitfield & type_mask) { largest_erase_type = i_ind; - if ((size > (int)(_erase_type_size_arr[largest_erase_type])) && - ((boundry - offset) > (int)(_erase_type_size_arr[largest_erase_type]))) { + if ((size > (int)(smtbl.erase_type_size_arr[largest_erase_type])) && + ((_sfdp_info.smtbl.region_high_boundary[region] - offset) + > (int)(smtbl.erase_type_size_arr[largest_erase_type]))) { break; } else { bitfield &= ~type_mask; @@ -954,10 +903,9 @@ int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, i } if (i_ind == 4) { - tr_error("no erase type was found for current region addr"); + tr_error("No erase type was found for current region addr"); } return largest_erase_type; - } /*********************************************/ diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h index d847d364b1f..e3595566502 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h @@ -52,9 +52,6 @@ enum spif_bd_error { }; -#define SPIF_MAX_REGIONS 10 -#define MAX_NUM_OF_ERASE_TYPES 4 - /** BlockDevice for SFDP based flash devices over SPI bus * * @code @@ -222,6 +219,10 @@ class SPIFBlockDevice : public mbed::BlockDevice { // Internal functions + // SFDP helpers + friend int mbed::sfdp_parse_headers(mbed::Callback sfdp_reader, + mbed::sfdp_hdr_info &hdr_info); + /****************************************/ /* SFDP Detection and Parsing Functions */ /****************************************/ @@ -234,9 +235,6 @@ class SPIFBlockDevice : public mbed::BlockDevice { // 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 Sector Map - int _sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size); - // 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, int &read_inst); @@ -246,17 +244,21 @@ class SPIFBlockDevice : public mbed::BlockDevice { // Detect all supported erase types int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &erase4k_inst, - int *erase_type_inst_arr, unsigned int *erase_type_size_arr); + mbed::sfdp_smtbl_info &smtbl); /***********************/ /* Utilities Functions */ /***********************/ // Find the region to which the given offset belongs to - int _utils_find_addr_region(bd_size_t offset) const; + int _utils_find_addr_region(bd_size_t offset, const mbed::sfdp_smtbl_info &smtbl) const; // Iterate on all supported Erase Types of the Region to which the offset belongs to. // Iterates from highest type to lowest - int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry); + int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, + int size, + int offset, + int region, + mbed::sfdp_smtbl_info &smtbl); /********************************/ /* Calls to SPI Driver APIs */ @@ -304,22 +306,8 @@ class SPIFBlockDevice : public mbed::BlockDevice { int _erase_instruction; int _erase4k_inst; // Legacy 4K erase instruction (default 0x20h) - // SFDP helpers - friend int mbed::sfdp_parse_headers(mbed::Callback sfdp_reader, - mbed::sfdp_hdr_info &hdr_info); - - - // Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size) - int _erase_type_inst_arr[MAX_NUM_OF_ERASE_TYPES]; - unsigned int _erase_type_size_arr[MAX_NUM_OF_ERASE_TYPES]; - - // Sector Regions Map - int _regions_count; //number of regions - int _region_size_bytes[SPIF_MAX_REGIONS]; //regions size in bytes - bd_size_t _region_high_boundary[SPIF_MAX_REGIONS]; //region high address offset boundary - //Each Region can support a bit combination of any of the 4 Erase Types - uint8_t _region_erase_types_bitfield[SPIF_MAX_REGIONS]; - unsigned int _min_common_erase_size; // minimal common erase size for all regions (0 if none exists) + // Data extracted from the devices SFDP structure + mbed::sfdp_hdr_info _sfdp_info; unsigned int _page_size_bytes; // Page size - 256 Bytes default bd_size_t _device_size_bytes; diff --git a/drivers/internal/SFDP.h b/drivers/internal/SFDP.h index 32e9cc4646d..612ea48a97c 100644 --- a/drivers/internal/SFDP.h +++ b/drivers/internal/SFDP.h @@ -31,6 +31,8 @@ static const int SFDP_SECTOR_MAP_MAX_REGIONS = 10; // Erase Types Per Region BitMask static const int SFDP_ERASE_BITMASK_TYPE4 = 0x08; +static const int SFDP_ERASE_BITMASK_TYPE3 = 0x04; +static const int SFDP_ERASE_BITMASK_TYPE2 = 0x02; static const int SFDP_ERASE_BITMASK_TYPE1 = 0x01; static const int SFDP_ERASE_BITMASK_NONE = 0x00; static const int SFDP_ERASE_BITMASK_ALL = 0x0F; From f51600c0894108dba6bbd3cc34cd889326ecd8c9 Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Mon, 27 Jan 2020 13:04:20 +0200 Subject: [PATCH 08/12] SPIFBlockDevice: drops unnecessary wrapper function --- .../storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp | 7 +------ .../storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h | 3 --- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp index ec8493534f1..871ec8bb384 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp @@ -175,7 +175,7 @@ int SPIFBlockDevice::init() } /**************************** Parse SFDP Header ***********************************/ - if (0 != _sfdp_parse_sfdp_headers(hdr_info)) { + if (0 != sfdp_parse_headers(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), hdr_info)) { tr_error("init - Parse SFDP Headers Failed"); status = SPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -665,11 +665,6 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, si return 0; } -int SPIFBlockDevice::_sfdp_parse_sfdp_headers(sfdp_hdr_info &hdr_info) -{ - return sfdp_parse_headers(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), hdr_info); -} - unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size) { unsigned int page_size = SPIF_DEFAULT_PAGE_SIZE; diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h index e3595566502..db780354256 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h @@ -229,9 +229,6 @@ class SPIFBlockDevice : public mbed::BlockDevice { // Send SFDP Read command to Driver int _spi_send_read_sfdp_command(mbed::bd_addr_t addr, void *rx_buffer, mbed::bd_size_t rx_length); - // Parse SFDP Headers and retrieve Basic Param and Sector Map Tables (if exist) - int _sfdp_parse_sfdp_headers(mbed::sfdp_hdr_info &hdr_info); - // Parse and Detect required Basic Parameters from Table int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size); From 4f4ef6069eb014c3d80a72bcc43e36af37082a6d Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Mon, 27 Jan 2020 15:26:53 +0200 Subject: [PATCH 09/12] SFDP: Sector Map Parameter Table naming improvements --- .../COMPONENT_QSPIF/QSPIFBlockDevice.cpp | 92 +++++++++--------- .../COMPONENT_QSPIF/QSPIFBlockDevice.h | 6 +- .../COMPONENT_SPIF/SPIFBlockDevice.cpp | 96 +++++++++---------- .../COMPONENT_SPIF/SPIFBlockDevice.h | 6 +- drivers/internal/SFDP.h | 6 +- drivers/source/SFDP.cpp | 30 +++--- 6 files changed, 118 insertions(+), 118 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index 9d85db42b90..a7f76c67d36 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -152,9 +152,9 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam } // Initialize parameters - _sfdp_info.smtbl.regions_min_common_erase_size = 0; - _sfdp_info.smtbl.region_cnt = 1; - _sfdp_info.smtbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE; + _sfdp_info.smptbl.regions_min_common_erase_size = 0; + _sfdp_info.smptbl.region_cnt = 1; + _sfdp_info.smptbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE; // Until proven otherwise, assume no quad enable _quad_enable_register_idx = QSPIF_NO_QUAD_ENABLE; @@ -200,8 +200,8 @@ int QSPIFBlockDevice::init() int status = QSPIF_BD_ERROR_OK; _sfdp_info.bptbl.addr = 0x0; _sfdp_info.bptbl.size = 0; - _sfdp_info.smtbl.addr = 0x0; - _sfdp_info.smtbl.size = 0; + _sfdp_info.smptbl.addr = 0x0; + _sfdp_info.smptbl.size = 0; _mutex.lock(); @@ -259,15 +259,15 @@ int QSPIFBlockDevice::init() } /**************************** Parse Sector Map Table ***********************************/ - _sfdp_info.smtbl.region_size[0] = + _sfdp_info.smptbl.region_size[0] = _device_size_bytes; // If there's no region map, we have a single region sized the entire device size - _sfdp_info.smtbl.region_high_boundary[0] = _device_size_bytes - 1; + _sfdp_info.smptbl.region_high_boundary[0] = _device_size_bytes - 1; - if ((_sfdp_info.smtbl.addr != 0) && (0 != _sfdp_info.smtbl.size)) { - tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", _sfdp_info.smtbl.addr, - _sfdp_info.smtbl.size); + if ((_sfdp_info.smptbl.addr != 0) && (0 != _sfdp_info.smptbl.size)) { + tr_debug("Init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", _sfdp_info.smptbl.addr, + _sfdp_info.smptbl.size); if (sfdp_parse_sector_map_table(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command), - _sfdp_info.smtbl) < 0) { + _sfdp_info.smptbl) < 0) { tr_error("Init - Parse Sector Map Table Failed"); status = QSPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -409,9 +409,9 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) bool erase_failed = false; int status = QSPIF_BD_ERROR_OK; // Find region of erased address - int region = _utils_find_addr_region(addr, _sfdp_info.smtbl); + int region = _utils_find_addr_region(addr, _sfdp_info.smptbl); // Erase Types of selected region - uint8_t bitfield = _sfdp_info.smtbl.region_erase_types_bitfld[region]; + uint8_t bitfield = _sfdp_info.smptbl.region_erase_types_bitfld[region]; tr_debug("Erase - addr: %llu, in_size: %llu", addr, in_size); @@ -433,9 +433,9 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) // Find the matching instruction and erase size chunk for that type. type = _utils_iterate_next_largest_erase_type(bitfield, size, (int)addr, region, - _sfdp_info.smtbl); - cur_erase_inst = _sfdp_info.smtbl.erase_type_inst_arr[type]; - eu_size = _sfdp_info.smtbl.erase_type_size_arr[type]; + _sfdp_info.smptbl); + cur_erase_inst = _sfdp_info.smptbl.erase_type_inst_arr[type]; + eu_size = _sfdp_info.smptbl.erase_type_size_arr[type]; } else { // Must use legacy 4k erase instruction cur_erase_inst = _legacy_erase_instruction; @@ -468,10 +468,10 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) addr += chunk; size -= chunk; - if ((size > 0) && (addr > _sfdp_info.smtbl.region_high_boundary[region])) { + if ((size > 0) && (addr > _sfdp_info.smptbl.region_high_boundary[region])) { // erase crossed to next region region++; - bitfield = _sfdp_info.smtbl.region_erase_types_bitfld[region]; + bitfield = _sfdp_info.smptbl.region_erase_types_bitfld[region]; } if (false == _is_mem_ready()) { @@ -507,7 +507,7 @@ bd_size_t QSPIFBlockDevice::get_program_size() const bd_size_t QSPIFBlockDevice::get_erase_size() const { // return minimal erase size supported by all regions (0 if none exists) - return _sfdp_info.smtbl.regions_min_common_erase_size; + return _sfdp_info.smptbl.regions_min_common_erase_size; } const char *QSPIFBlockDevice::get_type() const @@ -524,9 +524,9 @@ bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr) } // Find region of current address - int region = _utils_find_addr_region(addr, _sfdp_info.smtbl); + int region = _utils_find_addr_region(addr, _sfdp_info.smptbl); - int min_region_erase_size = _sfdp_info.smtbl.regions_min_common_erase_size; + int min_region_erase_size = _sfdp_info.smptbl.regions_min_common_erase_size; int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; int i_ind = 0; @@ -535,9 +535,9 @@ bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr) for (i_ind = 0; i_ind < 4; i_ind++) { // loop through erase types bitfield supported by region - if (_sfdp_info.smtbl.region_erase_types_bitfld[region] & type_mask) { + if (_sfdp_info.smptbl.region_erase_types_bitfld[region] & type_mask) { - min_region_erase_size = _sfdp_info.smtbl.erase_type_size_arr[i_ind]; + min_region_erase_size = _sfdp_info.smptbl.erase_type_size_arr[i_ind]; break; } type_mask = type_mask << 1; @@ -661,7 +661,7 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, s bool shouldSetQuadEnable = false; bool is_qpi_mode = false; - if (_sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _sfdp_info.smtbl) != 0) { + if (_sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _sfdp_info.smptbl) != 0) { tr_error("Init - Detecting erase types instructions/sizes failed"); return -1; } @@ -847,7 +847,7 @@ int QSPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int int QSPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, - sfdp_smtbl_info &smtbl) + sfdp_smptbl_info &smptbl) { uint8_t bitfield = 0x01; @@ -855,26 +855,26 @@ int QSPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_para if (basic_param_table_size > QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE) { // Loop Erase Types 1-4 for (int i_ind = 0; i_ind < 4; i_ind++) { - smtbl.erase_type_inst_arr[i_ind] = QSPI_NO_INST; // Default for unsupported type - smtbl.erase_type_size_arr[i_ind] = 1 + smptbl.erase_type_inst_arr[i_ind] = QSPI_NO_INST; // Default for unsupported type + smptbl.erase_type_size_arr[i_ind] = 1 << basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]; // Size is 2^N where N is the table value - tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smtbl.erase_type_inst_arr[i_ind], - smtbl.erase_type_size_arr[i_ind]); - if (smtbl.erase_type_size_arr[i_ind] > 1) { + tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smptbl.erase_type_inst_arr[i_ind], + smptbl.erase_type_size_arr[i_ind]); + if (smptbl.erase_type_size_arr[i_ind] > 1) { // if size==1 type is not supported - smtbl.erase_type_inst_arr[i_ind] = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE + smptbl.erase_type_inst_arr[i_ind] = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE + 2 * i_ind]; - if ((smtbl.erase_type_size_arr[i_ind] < smtbl.regions_min_common_erase_size) - || (smtbl.regions_min_common_erase_size == 0)) { + if ((smptbl.erase_type_size_arr[i_ind] < smptbl.regions_min_common_erase_size) + || (smptbl.regions_min_common_erase_size == 0)) { //Set default minimal common erase for signal region - smtbl.regions_min_common_erase_size = smtbl.erase_type_size_arr[i_ind]; + smptbl.regions_min_common_erase_size = smptbl.erase_type_size_arr[i_ind]; } - smtbl.region_erase_types_bitfld[0] |= bitfield; // If there's no region map, set region "0" types bitfield as default + smptbl.region_erase_types_bitfld[0] |= bitfield; // If there's no region map, set region "0" types bitfield as default } - tr_debug("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smtbl.erase_type_inst_arr[i_ind], - smtbl.erase_type_size_arr[i_ind]); + tr_debug("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smptbl.erase_type_inst_arr[i_ind], + smptbl.erase_type_size_arr[i_ind]); bitfield = bitfield << 1; } } else { @@ -1320,20 +1320,20 @@ bool QSPIFBlockDevice::_is_mem_ready() /*********************************************/ /************* Utility Functions *************/ /*********************************************/ -int QSPIFBlockDevice::_utils_find_addr_region(bd_size_t offset, sfdp_smtbl_info &smtbl) +int QSPIFBlockDevice::_utils_find_addr_region(bd_size_t offset, sfdp_smptbl_info &smptbl) { //Find the region to which the given offset belong to - if ((offset > _device_size_bytes) || (smtbl.region_cnt == 0)) { + if ((offset > _device_size_bytes) || (smptbl.region_cnt == 0)) { return -1; } - if (smtbl.region_cnt == 1) { + if (smptbl.region_cnt == 1) { return 0; } - for (int i_ind = smtbl.region_cnt - 2; i_ind >= 0; i_ind--) { + for (int i_ind = smptbl.region_cnt - 2; i_ind >= 0; i_ind--) { - if (offset > smtbl.region_high_boundary[i_ind]) { + if (offset > smptbl.region_high_boundary[i_ind]) { return (i_ind + 1); } } @@ -1345,7 +1345,7 @@ int QSPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int region, - sfdp_smtbl_info &smtbl) + sfdp_smptbl_info &smptbl) { // Iterate on all supported Erase Types of the Region to which the offset belong to. // Iterates from highest type to lowest @@ -1355,9 +1355,9 @@ int QSPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, for (i_ind = 3; i_ind >= 0; i_ind--) { if (bitfield & type_mask) { largest_erase_type = i_ind; - if ((size > (int)(smtbl.erase_type_size_arr[largest_erase_type])) && - ((_sfdp_info.smtbl.region_high_boundary[region] - offset) - > (int)(smtbl.erase_type_size_arr[largest_erase_type]))) { + if ((size > (int)(smptbl.erase_type_size_arr[largest_erase_type])) && + ((_sfdp_info.smptbl.region_high_boundary[region] - offset) + > (int)(smptbl.erase_type_size_arr[largest_erase_type]))) { break; } else { bitfield &= ~type_mask; diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h index 36bdbefa584..13d0f52b5a9 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h @@ -338,7 +338,7 @@ class QSPIFBlockDevice : public mbed::BlockDevice { // 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::sfdp_smtbl_info &smtbl); + mbed::sfdp_smptbl_info &smptbl); // 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); @@ -350,7 +350,7 @@ class QSPIFBlockDevice : public mbed::BlockDevice { /* Utilities Functions */ /***********************/ // Find the region to which the given offset belong to - int _utils_find_addr_region(mbed::bd_size_t offset, mbed::sfdp_smtbl_info &smtbl); + int _utils_find_addr_region(mbed::bd_size_t offset, mbed::sfdp_smptbl_info &smptbl); // Iterate on all supported Erase Types of the Region to which the offset belong to. // Iterates from highest type to lowest @@ -358,7 +358,7 @@ class QSPIFBlockDevice : public mbed::BlockDevice { int size, int offset, int region, - mbed::sfdp_smtbl_info &smtbl); + mbed::sfdp_smptbl_info &smptbl); private: enum qspif_clear_protection_method_t { diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp index 871ec8bb384..9b8cc88ebdc 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp @@ -107,9 +107,9 @@ SPIFBlockDevice::SPIFBlockDevice( _write_dummy_and_mode_cycles = 0; _dummy_and_mode_cycles = _read_dummy_and_mode_cycles; - _sfdp_info.smtbl.regions_min_common_erase_size = 0; - _sfdp_info.smtbl.region_cnt = 1; - _sfdp_info.smtbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE; + _sfdp_info.smptbl.regions_min_common_erase_size = 0; + _sfdp_info.smptbl.region_cnt = 1; + _sfdp_info.smptbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE; if (SPIF_BD_ERROR_OK != _spi_set_frequency(freq)) { tr_error("SPI Set Frequency Failed"); @@ -190,15 +190,15 @@ int SPIFBlockDevice::init() } /**************************** Parse Sector Map Table ***********************************/ - _sfdp_info.smtbl.region_size[0] = + _sfdp_info.smptbl.region_size[0] = _device_size_bytes; // If there's no region map, we have a single region sized the entire device size - _sfdp_info.smtbl.region_high_boundary[0] = _device_size_bytes - 1; + _sfdp_info.smptbl.region_high_boundary[0] = _device_size_bytes - 1; - if ((hdr_info.smtbl.addr != 0) && (0 != hdr_info.smtbl.size)) { - tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", hdr_info.smtbl.addr, - hdr_info.smtbl.size); + if ((hdr_info.smptbl.addr != 0) && (0 != hdr_info.smptbl.size)) { + tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", hdr_info.smptbl.addr, + hdr_info.smptbl.size); if (sfdp_parse_sector_map_table(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), - _sfdp_info.smtbl) < 0) { + _sfdp_info.smptbl) < 0) { tr_error("init - Parse Sector Map Table Failed"); status = SPIF_BD_ERROR_PARSING_FAILED; goto exit_point; @@ -342,13 +342,13 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) bool erase_failed = false; int status = SPIF_BD_ERROR_OK; // Find region of erased address - int region = _utils_find_addr_region(addr, _sfdp_info.smtbl); + int region = _utils_find_addr_region(addr, _sfdp_info.smptbl); if (region < 0) { tr_error("no region found for address %llu", addr); return SPIF_BD_ERROR_INVALID_ERASE_PARAMS; } // Erase Types of selected region - uint8_t bitfield = _sfdp_info.smtbl.region_erase_types_bitfld[region]; + uint8_t bitfield = _sfdp_info.smptbl.region_erase_types_bitfld[region]; tr_debug("erase - addr: %llu, in_size: %llu", addr, in_size); @@ -367,11 +367,11 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) // iterate to find next Largest erase type ( a. supported by region, b. smaller than size) // find the matching instruction and erase size chunk for that type. - type = _utils_iterate_next_largest_erase_type(bitfield, size, (unsigned int)addr, region, _sfdp_info.smtbl); - cur_erase_inst = _sfdp_info.smtbl.erase_type_inst_arr[type]; - offset = addr % _sfdp_info.smtbl.erase_type_size_arr[type]; - chunk = ((offset + size) < _sfdp_info.smtbl.erase_type_size_arr[type]) ? - size : (_sfdp_info.smtbl.erase_type_size_arr[type] - offset); + type = _utils_iterate_next_largest_erase_type(bitfield, size, (unsigned int)addr, region, _sfdp_info.smptbl); + cur_erase_inst = _sfdp_info.smptbl.erase_type_inst_arr[type]; + offset = addr % _sfdp_info.smptbl.erase_type_size_arr[type]; + chunk = ((offset + size) < _sfdp_info.smptbl.erase_type_size_arr[type]) ? + size : (_sfdp_info.smptbl.erase_type_size_arr[type] - offset); tr_debug("erase - addr: %llu, size:%d, Inst: 0x%xh, chunk: %" PRIu32 " , ", addr, size, cur_erase_inst, chunk); @@ -392,10 +392,10 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) addr += chunk; size -= chunk; - if ((size > 0) && (addr > _sfdp_info.smtbl.region_high_boundary[region])) { + if ((size > 0) && (addr > _sfdp_info.smptbl.region_high_boundary[region])) { // erase crossed to next region region++; - bitfield = _sfdp_info.smtbl.region_erase_types_bitfld[region]; + bitfield = _sfdp_info.smptbl.region_erase_types_bitfld[region]; } if (false == _is_mem_ready()) { @@ -431,16 +431,16 @@ bd_size_t SPIFBlockDevice::get_program_size() const bd_size_t SPIFBlockDevice::get_erase_size() const { // return minimal erase size supported by all regions (0 if none exists) - return _sfdp_info.smtbl.regions_min_common_erase_size; + return _sfdp_info.smptbl.regions_min_common_erase_size; } // Find minimal erase size supported by the region to which the address belongs to bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr) const { // Find region of current address - int region = _utils_find_addr_region(addr, _sfdp_info.smtbl); + int region = _utils_find_addr_region(addr, _sfdp_info.smptbl); - unsigned int min_region_erase_size = _sfdp_info.smtbl.regions_min_common_erase_size; + unsigned int min_region_erase_size = _sfdp_info.smptbl.regions_min_common_erase_size; int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; int i_ind = 0; @@ -449,9 +449,9 @@ bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr) const for (i_ind = 0; i_ind < 4; i_ind++) { // loop through erase types bitfield supported by region - if (_sfdp_info.smtbl.region_erase_types_bitfld[region] & type_mask) { + if (_sfdp_info.smptbl.region_erase_types_bitfld[region] & type_mask) { - min_region_erase_size = _sfdp_info.smtbl.erase_type_size_arr[i_ind]; + min_region_erase_size = _sfdp_info.smptbl.erase_type_size_arr[i_ind]; break; } type_mask = type_mask << 1; @@ -656,7 +656,7 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, si _page_size_bytes = _sfdp_detect_page_size(param_table, basic_table_size); // Detect and Set Erase Types - _sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _erase4k_inst, _sfdp_info.smtbl); + _sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _erase4k_inst, _sfdp_info.smptbl); _erase_instruction = _erase4k_inst; // Detect and Set fastest Bus mode (default 1-1-1) @@ -682,7 +682,7 @@ unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &erase4k_inst, - sfdp_smtbl_info &smtbl) + sfdp_smptbl_info &smptbl) { erase4k_inst = 0xff; bool found_4Kerase_type = false; @@ -694,36 +694,36 @@ int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param if (basic_param_table_size > SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE) { // Loop Erase Types 1-4 for (int i_ind = 0; i_ind < 4; i_ind++) { - smtbl.erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type - smtbl.erase_type_size_arr[i_ind] = local_math_power( + smptbl.erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type + smptbl.erase_type_size_arr[i_ind] = local_math_power( 2, basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N - tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smtbl.erase_type_inst_arr[i_ind], - smtbl.erase_type_size_arr[i_ind]); - if (smtbl.erase_type_size_arr[i_ind] > 1) { + tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smptbl.erase_type_inst_arr[i_ind], + smptbl.erase_type_size_arr[i_ind]); + if (smptbl.erase_type_size_arr[i_ind] > 1) { // if size==1 type is not supported - smtbl.erase_type_inst_arr[i_ind] = + smptbl.erase_type_inst_arr[i_ind] = basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind]; - if ((smtbl.erase_type_size_arr[i_ind] < smtbl.regions_min_common_erase_size) - || (smtbl.regions_min_common_erase_size == 0)) { + if ((smptbl.erase_type_size_arr[i_ind] < smptbl.regions_min_common_erase_size) + || (smptbl.regions_min_common_erase_size == 0)) { //Set default minimal common erase for singal region - smtbl.regions_min_common_erase_size = smtbl.erase_type_size_arr[i_ind]; + smptbl.regions_min_common_erase_size = smptbl.erase_type_size_arr[i_ind]; } // SFDP standard requires 4K Erase type to exist and its instruction to be identical to legacy field erase instruction - if (smtbl.erase_type_size_arr[i_ind] == 4096) { + if (smptbl.erase_type_size_arr[i_ind] == 4096) { found_4Kerase_type = true; - if (erase4k_inst != smtbl.erase_type_inst_arr[i_ind]) { + if (erase4k_inst != smptbl.erase_type_inst_arr[i_ind]) { //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table - erase4k_inst = smtbl.erase_type_inst_arr[i_ind]; + erase4k_inst = smptbl.erase_type_inst_arr[i_ind]; tr_warning("_detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K"); } } - smtbl.region_erase_types_bitfld[0] |= bitfield; // no region map, set region "0" types bitfield as default + smptbl.region_erase_types_bitfld[0] |= bitfield; // no region map, set region "0" types bitfield as default } tr_info("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), - smtbl.erase_type_inst_arr[i_ind], smtbl.erase_type_size_arr[i_ind]); + smptbl.erase_type_inst_arr[i_ind], smptbl.erase_type_size_arr[i_ind]); bitfield = bitfield << 1; } } @@ -851,20 +851,20 @@ int SPIFBlockDevice::_set_write_enable() /*********************************************/ /************* Utility Functions *************/ /*********************************************/ -int SPIFBlockDevice::_utils_find_addr_region(bd_size_t offset, const sfdp_smtbl_info &smtbl) const +int SPIFBlockDevice::_utils_find_addr_region(bd_size_t offset, const sfdp_smptbl_info &smptbl) const { //Find the region to which the given offset belong to - if ((offset > _device_size_bytes) || (smtbl.region_cnt == 0)) { + if ((offset > _device_size_bytes) || (smptbl.region_cnt == 0)) { return -1; } - if (smtbl.region_cnt == 1) { + if (smptbl.region_cnt == 1) { return 0; } - for (int i_ind = smtbl.region_cnt - 2; i_ind >= 0; i_ind--) { + for (int i_ind = smptbl.region_cnt - 2; i_ind >= 0; i_ind--) { - if (offset > smtbl.region_high_boundary[i_ind]) { + if (offset > smptbl.region_high_boundary[i_ind]) { return (i_ind + 1); } } @@ -876,7 +876,7 @@ int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int region, - sfdp_smtbl_info &smtbl) + sfdp_smptbl_info &smptbl) { // Iterate on all supported Erase Types of the Region to which the offset belong to. // Iterates from highest type to lowest @@ -886,9 +886,9 @@ int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, for (i_ind = 3; i_ind >= 0; i_ind--) { if (bitfield & type_mask) { largest_erase_type = i_ind; - if ((size > (int)(smtbl.erase_type_size_arr[largest_erase_type])) && - ((_sfdp_info.smtbl.region_high_boundary[region] - offset) - > (int)(smtbl.erase_type_size_arr[largest_erase_type]))) { + if ((size > (int)(smptbl.erase_type_size_arr[largest_erase_type])) && + ((_sfdp_info.smptbl.region_high_boundary[region] - offset) + > (int)(smptbl.erase_type_size_arr[largest_erase_type]))) { break; } else { bitfield &= ~type_mask; diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h index db780354256..081c79b535c 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h @@ -241,13 +241,13 @@ class SPIFBlockDevice : public mbed::BlockDevice { // Detect all supported erase types int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &erase4k_inst, - mbed::sfdp_smtbl_info &smtbl); + mbed::sfdp_smptbl_info &smptbl); /***********************/ /* Utilities Functions */ /***********************/ // Find the region to which the given offset belongs to - int _utils_find_addr_region(bd_size_t offset, const mbed::sfdp_smtbl_info &smtbl) const; + int _utils_find_addr_region(bd_size_t offset, const mbed::sfdp_smptbl_info &smptbl) const; // Iterate on all supported Erase Types of the Region to which the offset belongs to. // Iterates from highest type to lowest @@ -255,7 +255,7 @@ class SPIFBlockDevice : public mbed::BlockDevice { int size, int offset, int region, - mbed::sfdp_smtbl_info &smtbl); + mbed::sfdp_smptbl_info &smptbl); /********************************/ /* Calls to SPI Driver APIs */ diff --git a/drivers/internal/SFDP.h b/drivers/internal/SFDP.h index 612ea48a97c..ba8ae5ff9d8 100644 --- a/drivers/internal/SFDP.h +++ b/drivers/internal/SFDP.h @@ -46,7 +46,7 @@ struct sfdp_bptbl_info { }; /** SFDP Sector Map Table info */ -struct sfdp_smtbl_info { +struct sfdp_smptbl_info { uint32_t addr; size_t size; int region_cnt; @@ -63,7 +63,7 @@ struct sfdp_smtbl_info { /** SFDP Parameter Table addresses and sizes */ struct sfdp_hdr_info { sfdp_bptbl_info bptbl; - sfdp_smtbl_info smtbl; + sfdp_smptbl_info smptbl; }; /** SFDP Header */ @@ -118,7 +118,7 @@ int sfdp_parse_headers(Callback sfdp_reader, * * @return 0 on success, negative error code on failure */ -int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smtbl_info &smtbl); +int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smptbl_info &smtbl); } /* namespace mbed */ #endif diff --git a/drivers/source/SFDP.cpp b/drivers/source/SFDP.cpp index ef909f9f870..eb8cbce7e5c 100644 --- a/drivers/source/SFDP.cpp +++ b/drivers/source/SFDP.cpp @@ -72,8 +72,8 @@ int sfdp_parse_single_param_header(sfdp_prm_hdr *phdr, sfdp_hdr_info &hdr_info) } else if ((phdr->PID_LSB == 0x81) && (sfdp_get_param_id_msb(phdr->DWORD2) == 0xFF)) { tr_debug("Parameter Header: Sector Map Parameter Header"); - hdr_info.smtbl.addr = sfdp_get_param_tbl_ptr(phdr->DWORD2); - hdr_info.smtbl.size = phdr->P_LEN * 4; + hdr_info.smptbl.addr = sfdp_get_param_tbl_ptr(phdr->DWORD2); + hdr_info.smptbl.size = phdr->P_LEN * 4; } else { tr_debug("Parameter Header vendor specific or unknown. Parameter ID LSB: 0x%" PRIX8 "; MSB: 0x%" PRIX8 "", @@ -134,7 +134,7 @@ int sfdp_parse_headers(Callback sfdp_reader, return 0; } -int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smtbl_info &smtbl) +int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smptbl_info &smptbl) { uint8_t sector_map_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */ uint32_t tmp_region_size = 0; @@ -143,7 +143,7 @@ int sfdp_parse_sector_map_table(Callback sfdp // Default set to all type bits 1-4 are common int min_common_erase_type_bits = SFDP_ERASE_BITMASK_ALL; - int status = sfdp_reader(smtbl.addr, sector_map_table, smtbl.size); + int status = sfdp_reader(smptbl.addr, sector_map_table, smptbl.size); if (status < 0) { tr_error("table retrieval failed"); return -1; @@ -155,30 +155,30 @@ int sfdp_parse_sector_map_table(Callback sfdp return -1; } - smtbl.region_cnt = sector_map_table[2] + 1; - if (smtbl.region_cnt > SFDP_SECTOR_MAP_MAX_REGIONS) { + smptbl.region_cnt = sector_map_table[2] + 1; + if (smptbl.region_cnt > SFDP_SECTOR_MAP_MAX_REGIONS) { tr_error("Supporting up to %d regions, current setup to %d regions - fail", SFDP_SECTOR_MAP_MAX_REGIONS, - smtbl.region_cnt); + smptbl.region_cnt); return -1; } // Loop through Regions and set for each one: size, supported erase types, high boundary offset // Calculate minimum Common Erase Type for all Regions - for (i_ind = 0; i_ind < smtbl.region_cnt; i_ind++) { + for (i_ind = 0; i_ind < smptbl.region_cnt; i_ind++) { tmp_region_size = ((*((uint32_t *)§or_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32 - smtbl.region_size[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes; - smtbl.region_erase_types_bitfld[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4 - min_common_erase_type_bits &= smtbl.region_erase_types_bitfld[i_ind]; - smtbl.region_high_boundary[i_ind] = (smtbl.region_size[i_ind] - 1) + prev_boundary; - prev_boundary = smtbl.region_high_boundary[i_ind] + 1; + smptbl.region_size[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes; + smptbl.region_erase_types_bitfld[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4 + min_common_erase_type_bits &= smptbl.region_erase_types_bitfld[i_ind]; + smptbl.region_high_boundary[i_ind] = (smptbl.region_size[i_ind] - 1) + prev_boundary; + prev_boundary = smptbl.region_high_boundary[i_ind] + 1; } // Calc minimum Common Erase Size from min_common_erase_type_bits uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; for (i_ind = 0; i_ind < 4; i_ind++) { if (min_common_erase_type_bits & type_mask) { - smtbl.regions_min_common_erase_size = smtbl.erase_type_size_arr[i_ind]; + smptbl.regions_min_common_erase_size = smptbl.erase_type_size_arr[i_ind]; break; } type_mask = type_mask << 1; @@ -186,7 +186,7 @@ int sfdp_parse_sector_map_table(Callback sfdp if (i_ind == 4) { // No common erase type was found between regions - smtbl.regions_min_common_erase_size = 0; + smptbl.regions_min_common_erase_size = 0; } return 0; From 3ee153a303424a8633422b26e4320ad3dae5205b Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Tue, 28 Jan 2020 12:36:24 +0200 Subject: [PATCH 10/12] test config: SPIF - overwrite QSPIF with all devices --- tools/test_configs/SPIFBlockDeviceAndHeapBlockDevice.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/test_configs/SPIFBlockDeviceAndHeapBlockDevice.json b/tools/test_configs/SPIFBlockDeviceAndHeapBlockDevice.json index 05be4d17ff8..e03c15084ab 100644 --- a/tools/test_configs/SPIFBlockDeviceAndHeapBlockDevice.json +++ b/tools/test_configs/SPIFBlockDeviceAndHeapBlockDevice.json @@ -17,7 +17,7 @@ } }, "target_overrides": { - "NRF52840_DK": { + "*": { "target.components_remove": ["QSPI", "QSPIF"], "target.components_add" : ["SPI", "SPIF"] } From ba71b09902e0af60c6ab0bca38d6521e402d4d95 Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Tue, 28 Jan 2020 15:54:06 +0200 Subject: [PATCH 11/12] astyle fixes --- .../storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp | 4 ++-- .../storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp | 2 +- drivers/source/SFDP.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index a7f76c67d36..d82ceaabc0f 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -857,13 +857,13 @@ int QSPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_para for (int i_ind = 0; i_ind < 4; i_ind++) { smptbl.erase_type_inst_arr[i_ind] = QSPI_NO_INST; // Default for unsupported type smptbl.erase_type_size_arr[i_ind] = 1 - << basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]; // Size is 2^N where N is the table value + << basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]; // Size is 2^N where N is the table value tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smptbl.erase_type_inst_arr[i_ind], smptbl.erase_type_size_arr[i_ind]); if (smptbl.erase_type_size_arr[i_ind] > 1) { // if size==1 type is not supported smptbl.erase_type_inst_arr[i_ind] = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE - + 2 * i_ind]; + + 2 * i_ind]; if ((smptbl.erase_type_size_arr[i_ind] < smptbl.regions_min_common_erase_size) || (smptbl.regions_min_common_erase_size == 0)) { diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp index 9b8cc88ebdc..18373e19411 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp @@ -696,7 +696,7 @@ int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param for (int i_ind = 0; i_ind < 4; i_ind++) { smptbl.erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type smptbl.erase_type_size_arr[i_ind] = local_math_power( - 2, basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N + 2, basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smptbl.erase_type_inst_arr[i_ind], smptbl.erase_type_size_arr[i_ind]); if (smptbl.erase_type_size_arr[i_ind] > 1) { diff --git a/drivers/source/SFDP.cpp b/drivers/source/SFDP.cpp index eb8cbce7e5c..5f43192a8e7 100644 --- a/drivers/source/SFDP.cpp +++ b/drivers/source/SFDP.cpp @@ -134,7 +134,7 @@ int sfdp_parse_headers(Callback sfdp_reader, return 0; } -int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smptbl_info &smptbl) +int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smptbl_info &smptbl) { uint8_t sector_map_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */ uint32_t tmp_region_size = 0; From e784c15c9e45acc6a8f71f78ba53b92fec3eb2df Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Wed, 29 Jan 2020 13:14:22 +0200 Subject: [PATCH 12/12] SFDP: doxygen improvements --- drivers/internal/SFDP.h | 79 ++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/drivers/internal/SFDP.h b/drivers/internal/SFDP.h index ba8ae5ff9d8..44d3ed0eb94 100644 --- a/drivers/internal/SFDP.h +++ b/drivers/internal/SFDP.h @@ -25,39 +25,45 @@ namespace mbed { -static const int SFDP_HEADER_SIZE = 8; ///< Size of an SFDP header */ -static const int SFDP_BASIC_PARAMS_TBL_SIZE = 80; ///< Basic Parameter Table size in Bytes, 20 DWORDS */ -static const int SFDP_SECTOR_MAP_MAX_REGIONS = 10; +/** \defgroup drivers-internal-api-sfdp SFDP + * \ingroup drivers-internal-api + * Serial Flash Discoverable Parameters. + * + * Based on JESD216D.01 Standard. + * @{ + */ + +static const int SFDP_HEADER_SIZE = 8; ///< Size of an SFDP header in bytes, 2 DWORDS +static const int SFDP_BASIC_PARAMS_TBL_SIZE = 80; ///< Basic Parameter Table size in bytes, 20 DWORDS +static const int SFDP_SECTOR_MAP_MAX_REGIONS = 10; ///< Maximum number of regions with different erase granularity // Erase Types Per Region BitMask -static const int SFDP_ERASE_BITMASK_TYPE4 = 0x08; -static const int SFDP_ERASE_BITMASK_TYPE3 = 0x04; -static const int SFDP_ERASE_BITMASK_TYPE2 = 0x02; -static const int SFDP_ERASE_BITMASK_TYPE1 = 0x01; -static const int SFDP_ERASE_BITMASK_NONE = 0x00; -static const int SFDP_ERASE_BITMASK_ALL = 0x0F; +static const int SFDP_ERASE_BITMASK_TYPE4 = 0x08; ///< Erase type 4 (erase granularity) identifier +static const int SFDP_ERASE_BITMASK_TYPE3 = 0x04; ///< Erase type 3 (erase granularity) identifier +static const int SFDP_ERASE_BITMASK_TYPE2 = 0x02; ///< Erase type 2 (erase granularity) identifier +static const int SFDP_ERASE_BITMASK_TYPE1 = 0x01; ///< Erase type 1 (erase granularity) identifier +static const int SFDP_ERASE_BITMASK_NONE = 0x00; ///< Erase type None +static const int SFDP_ERASE_BITMASK_ALL = 0x0F; ///< Erase type All -static const int SFDP_MAX_NUM_OF_ERASE_TYPES = 4; +static const int SFDP_MAX_NUM_OF_ERASE_TYPES = 4; ///< Maximum number of different erase types (erase granularity) /** SFDP Basic Parameter Table info */ struct sfdp_bptbl_info { - uint32_t addr; - size_t size; + uint32_t addr; ///< Address + size_t size; ///< Size }; /** SFDP Sector Map Table info */ struct sfdp_smptbl_info { - uint32_t addr; - size_t size; - int region_cnt; - int region_size[SFDP_SECTOR_MAP_MAX_REGIONS]; // [Bytes] - //Each Region can support a bit combination of any of the 4 Erase Types - uint8_t region_erase_types_bitfld[SFDP_SECTOR_MAP_MAX_REGIONS]; - unsigned int regions_min_common_erase_size; // minimal common erase size for all regions (0 if none exists) - bd_size_t region_high_boundary[SFDP_SECTOR_MAP_MAX_REGIONS]; //region high address offset boundary - // Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size) - int erase_type_inst_arr[SFDP_MAX_NUM_OF_ERASE_TYPES]; - unsigned int erase_type_size_arr[SFDP_MAX_NUM_OF_ERASE_TYPES]; + uint32_t addr; ///< Address + size_t size; ///< Size + int region_cnt; ///< Number of erase regions + int region_size[SFDP_SECTOR_MAP_MAX_REGIONS]; ///< Erase region size in bytes + uint8_t region_erase_types_bitfld[SFDP_SECTOR_MAP_MAX_REGIONS]; ///< Each Region can support a bit combination of any of the 4 Erase Types + unsigned int regions_min_common_erase_size; ///< Minimal common erase size for all regions (0 if none exists) + bd_size_t region_high_boundary[SFDP_SECTOR_MAP_MAX_REGIONS]; ///< Region high address offset boundary + int erase_type_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) + unsigned int erase_type_size_arr[SFDP_MAX_NUM_OF_ERASE_TYPES]; ///< Erase sizes for all different erase types }; /** SFDP Parameter Table addresses and sizes */ @@ -68,23 +74,23 @@ struct sfdp_hdr_info { /** SFDP Header */ struct sfdp_hdr { - uint8_t SIG_B0; // SFDP Signature, Byte 0 - uint8_t SIG_B1; // SFDP Signature, Byte 1 - uint8_t SIG_B2; // SFDP Signature, Byte 2 - uint8_t SIG_B3; // SFDP Signature, Byte 3 - uint8_t R_MINOR; // SFDP Minor Revision - uint8_t R_MAJOR; // SFDP Major Revision - uint8_t NPH; // Number of parameter headers (0-based, 0 indicates 1 parameter header) - uint8_t ACP; // SFDP Access Protocol + uint8_t SIG_B0; ///< SFDP Signature, Byte 0 + uint8_t SIG_B1; ///< SFDP Signature, Byte 1 + uint8_t SIG_B2; ///< SFDP Signature, Byte 2 + uint8_t SIG_B3; ///< SFDP Signature, Byte 3 + uint8_t R_MINOR; ///< SFDP Minor Revision + uint8_t R_MAJOR; ///< SFDP Major Revision + uint8_t NPH; ///< Number of parameter headers (0-based, 0 indicates 1 parameter header) + uint8_t ACP; ///< SFDP Access Protocol }; /** SFDP Parameter header */ struct sfdp_prm_hdr { - uint8_t PID_LSB; // Parameter ID LSB - uint8_t P_MINOR; // Parameter Minor Revision - uint8_t P_MAJOR; // Parameter Major Revision - uint8_t P_LEN; // Parameter length in DWORDS - uint32_t DWORD2; // Parameter ID MSB + Parameter Table Pointer + uint8_t PID_LSB; ///< Parameter ID LSB + uint8_t P_MINOR; ///< Parameter Minor Revision + uint8_t P_MAJOR; ///< Parameter Major Revision + uint8_t P_LEN; ///< Parameter length in DWORDS + uint32_t DWORD2; ///< Parameter ID MSB + Parameter Table Pointer }; /** Parse SFDP Header @@ -120,5 +126,6 @@ int sfdp_parse_headers(Callback sfdp_reader, */ int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smptbl_info &smtbl); +/** @}*/ } /* namespace mbed */ #endif