diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index a7e1ae62af..39ec37842e 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -125,10 +125,12 @@ PinName *QSPIFBlockDevice::_active_qspif_flash_csel_arr = generate_initialized_a /********* Public API Functions *********/ /****************************************/ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel, - int clock_mode, int freq) - : _qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _csel(csel), _freq(freq), _device_size_bytes(0), - _init_ref_count(0), - _is_initialized(false) + int clock_mode, + int freq) + : + _qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _csel(csel), _freq(freq), + _init_ref_count(0), + _is_initialized(false) { _unique_device_status = add_new_csel_instance(csel); @@ -142,6 +144,7 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam // Initialize parameters _sfdp_info.bptbl.legacy_erase_instruction = QSPIF_INST_LEGACY_ERASE_DEFAULT; + _sfdp_info.bptbl.device_size_bytes = 0; _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; @@ -249,9 +252,8 @@ int QSPIFBlockDevice::init() } /**************************** Parse Sector Map Table ***********************************/ - _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.smptbl.region_high_boundary[0] = _device_size_bytes - 1; + _sfdp_info.smptbl.region_size[0] = _sfdp_info.bptbl.device_size_bytes; // If there's no region map, we have a single region sized the entire device size + _sfdp_info.smptbl.region_high_boundary[0] = _sfdp_info.bptbl.device_size_bytes - 1; 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, @@ -399,13 +401,13 @@ 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.smptbl); + int region = sfdp_find_addr_region(addr, _sfdp_info); // Erase Types of selected region uint8_t bitfield = _sfdp_info.smptbl.region_erase_types_bitfld[region]; tr_debug("Erase - addr: %llu, in_size: %llu", addr, in_size); - if ((addr + in_size) > _device_size_bytes) { + if ((addr + in_size) > _sfdp_info.bptbl.device_size_bytes) { tr_error("Erase exceeds flash device size"); return QSPIF_BD_ERROR_INVALID_ERASE_PARAMS; } @@ -421,9 +423,9 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) if (_sfdp_info.bptbl.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, - _sfdp_info.smptbl); + type = sfdp_iterate_next_largest_erase_type(bitfield, size, (int)addr, + region, + _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 { @@ -514,7 +516,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.smptbl); + int region = sfdp_find_addr_region(addr, _sfdp_info); int min_region_erase_size = _sfdp_info.smptbl.regions_min_common_erase_size; int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; @@ -543,7 +545,7 @@ bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr) bd_size_t QSPIFBlockDevice::size() const { - return _device_size_bytes; + return _sfdp_info.bptbl.device_size_bytes; } int QSPIFBlockDevice::get_erase_value() const @@ -638,7 +640,7 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(Callback _device_size_bytes) || (smptbl.region_cnt == 0)) { - return -1; - } - - if (smptbl.region_cnt == 1) { - return 0; - } - - for (int i_ind = smptbl.region_cnt - 2; i_ind >= 0; i_ind--) { - - if (offset > smptbl.region_high_boundary[i_ind]) { - return (i_ind + 1); - } - } - return -1; - -} - -int QSPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, - int size, - int offset, - int region, - 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 - 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)(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; - } - } - type_mask = type_mask >> 1; - } - - if (i_ind == 4) { - tr_error("No erase type was found for current region addr"); - } - return largest_erase_type; -} - /***************************************************/ /*********** QSPI Driver API Functions *************/ /***************************************************/ diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h index aa0ff64623..d518a82094 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h @@ -249,14 +249,6 @@ public: virtual const char *get_type() const; private: - - // SFDP helpers - friend int mbed::sfdp_parse_headers(mbed::Callback sfdp_reader, - mbed::sfdp_hdr_info &hdr_info); - - // Internal functions - - /********************************/ /* Different Device Csel Mgmt */ /********************************/ @@ -334,9 +326,6 @@ private: // Enable QPI mode (4-4-4) int _sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr); - // Set Page size for program - int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size); - // Detect 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); @@ -407,7 +396,6 @@ private: unsigned int _page_size_bytes; // Page size - 256 Bytes default int _freq; - bd_size_t _device_size_bytes; // Bus speed configuration qspi_bus_width_t _inst_width; //Bus width for Instruction phase diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp index da65642fee..0768c52d39 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp @@ -85,12 +85,10 @@ SingletonPtr SPIFBlockDevice::_mutex; //*********************** // SPIF Block Device APIs //*********************** -SPIFBlockDevice::SPIFBlockDevice( - PinName mosi, PinName miso, PinName sclk, PinName csel, int freq) +SPIFBlockDevice::SPIFBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName csel, int freq) : _spi(mosi, miso, sclk), _cs(csel), _prog_instruction(0), _erase_instruction(0), - _page_size_bytes(0), - _device_size_bytes(0), _init_ref_count(0), _is_initialized(false) + _page_size_bytes(0), _init_ref_count(0), _is_initialized(false) { _address_size = SPIF_ADDR_SIZE_3_BYTES; // Initial SFDP read tables are read with 8 dummy cycles @@ -99,6 +97,7 @@ SPIFBlockDevice::SPIFBlockDevice( _write_dummy_and_mode_cycles = 0; _dummy_and_mode_cycles = _read_dummy_and_mode_cycles; + _sfdp_info.bptbl.device_size_bytes = 0; _sfdp_info.bptbl.legacy_erase_instruction = SPIF_INST_LEGACY_ERASE_DEFAULT; _sfdp_info.smptbl.regions_min_common_erase_size = 0; _sfdp_info.smptbl.region_cnt = 1; @@ -188,9 +187,9 @@ int SPIFBlockDevice::init() } /**************************** Parse Sector Map Table ***********************************/ - _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.smptbl.region_high_boundary[0] = _device_size_bytes - 1; + _sfdp_info.smptbl.region_size[0] = _sfdp_info.bptbl.device_size_bytes; + // If there's no region map, we have a single region sized the entire device size + _sfdp_info.smptbl.region_high_boundary[0] = _sfdp_info.bptbl.device_size_bytes - 1; if ((_sfdp_info.smptbl.addr != 0) && (0 != _sfdp_info.smptbl.size)) { tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", _sfdp_info.smptbl.addr, @@ -207,9 +206,9 @@ int SPIFBlockDevice::init() // Dummy And Mode Cycles Back default 0 _dummy_and_mode_cycles = _write_dummy_and_mode_cycles; _is_initialized = true; - tr_debug("Device size: %llu Kbytes", _device_size_bytes / 1024); + tr_debug("Device size: %llu Kbytes", _sfdp_info.bptbl.device_size_bytes / 1024); - if (_device_size_bytes > (1 << 24)) { + if (_sfdp_info.bptbl.device_size_bytes > (1 << 24)) { tr_debug("Size is bigger than 16MB and thus address does not fit in 3 byte, switch to 4 byte address mode"); _spi_send_general_command(SPIF_4BEN, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0); _address_size = SPIF_ADDR_SIZE_4_BYTES; @@ -340,7 +339,7 @@ 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.smptbl); + int region = sfdp_find_addr_region(addr, _sfdp_info); if (region < 0) { tr_error("no region found for address %llu", addr); return SPIF_BD_ERROR_INVALID_ERASE_PARAMS; @@ -350,7 +349,7 @@ int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) tr_debug("erase - addr: %llu, in_size: %llu", addr, in_size); - if ((addr + in_size) > _device_size_bytes) { + if ((addr + in_size) > _sfdp_info.bptbl.device_size_bytes) { tr_error("erase exceeds flash device size"); return SPIF_BD_ERROR_INVALID_ERASE_PARAMS; } @@ -365,7 +364,7 @@ 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.smptbl); + type = sfdp_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]) ? @@ -436,7 +435,7 @@ bd_size_t SPIFBlockDevice::get_erase_size() const 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.smptbl); + int region = sfdp_find_addr_region(addr, _sfdp_info); unsigned int min_region_erase_size = _sfdp_info.smptbl.regions_min_common_erase_size; int8_t type_mask = SFDP_ERASE_BITMASK_TYPE1; @@ -469,7 +468,7 @@ bd_size_t SPIFBlockDevice::size() const return 0; } - return _device_size_bytes; + return _sfdp_info.bptbl.device_size_bytes; } int SPIFBlockDevice::get_erase_value() const @@ -641,8 +640,8 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(Callback _device_size_bytes) || (smptbl.region_cnt == 0)) { - return -1; - } - - if (smptbl.region_cnt == 1) { - return 0; - } - - for (int i_ind = smptbl.region_cnt - 2; i_ind >= 0; i_ind--) { - - if (offset > smptbl.region_high_boundary[i_ind]) { - return (i_ind + 1); - } - } - return -1; - -} - -int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, - int size, - int offset, - int region, - 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 - 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)(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; - } - } - type_mask = type_mask >> 1; - } - - if (i_ind == 4) { - 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 8ea0bab8ed..e5bece0862 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h @@ -217,13 +217,6 @@ public: virtual const char *get_type() const; private: - - // 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 */ /****************************************/ @@ -237,23 +230,6 @@ private: // 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); - // Set Page size for program - unsigned int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size); - - /***********************/ - /* Utilities Functions */ - /***********************/ - // Find the region to which the given offset belongs to - 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 - int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, - int size, - int offset, - int region, - mbed::sfdp_smptbl_info &smptbl); - /********************************/ /* Calls to SPI Driver APIs */ /********************************/ diff --git a/drivers/internal/SFDP.h b/drivers/internal/SFDP.h index 9db4841573..46f2d1f4c5 100644 --- a/drivers/internal/SFDP.h +++ b/drivers/internal/SFDP.h @@ -47,14 +47,15 @@ constexpr int SFDP_ERASE_BITMASK_ALL = 0x0F; ///< Erase type All constexpr int SFDP_MAX_NUM_OF_ERASE_TYPES = 4; ///< Maximum number of different erase types (erase granularity) -/** SFDP Basic Parameter Table info */ +/** JEDEC Basic Flash Parameter Table info */ struct sfdp_bptbl_info { uint32_t addr; ///< Address size_t size; ///< Size + bd_size_t device_size_bytes; int legacy_erase_instruction; ///< Legacy 4K erase instruction }; -/** SFDP Sector Map Table info */ +/** JEDEC Sector Map Table info */ struct sfdp_smptbl_info { uint32_t addr; ///< Address size_t size; ///< Size @@ -67,36 +68,38 @@ struct sfdp_smptbl_info { 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 */ +/** SFDP JEDEC Parameter Table info */ struct sfdp_hdr_info { sfdp_bptbl_info bptbl; sfdp_smptbl_info smptbl; }; -/** Parse SFDP Headers - * Retrieves SFDP headers from a device and parses the information contained by the headers +/** Parse SFDP Database + * Retrieves all headers from within a memory device and parses the information contained by the headers * - * @param sfdp_reader Callback function used to read headers from a device - * @param hdr_info All information parsed from the headers gets passed back on this structure + * Only JEDEC headers are parsed, not vendor specific ones. * - * @return 0 on success, negative error code on failure + * @param sfdp_reader Callback function used to read headers from within a device + * @param[out] sfdp_info Contains the results of parsing the SFDP Database JEDEC headers + * + * @return MBED_SUCCESS on success, negative error code on failure */ -int sfdp_parse_headers(Callback sfdp_reader, sfdp_hdr_info &hdr_info); +int sfdp_parse_headers(Callback sfdp_reader, sfdp_hdr_info &sfdp_info); /** 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 + * @param sfdp_reader Callback function used to read headers from within a device + * @param[out] smtbl Contains the results of parsing the JEDEC Sector Map Table * - * @return 0 on success, negative error code on failure + * @return MBED_SUCCESS on success, negative error code on failure */ int sfdp_parse_sector_map_table(Callback sfdp_reader, sfdp_smptbl_info &smtbl); /** Detect page size used for writing on flash * - * @param bptbl_ptr Pointer to memory holding a Basic Parameter Table structure - * @param bptbl_size Size of memory holding a Basic Parameter Table + * @param bptbl_ptr Pointer to memory holding a Basic Parameter Table structure + * @param bptbl_size Size of memory holding the Basic Parameter Table * * @return Page size */ @@ -104,13 +107,40 @@ size_t sfdp_detect_page_size(uint8_t *bptbl_ptr, size_t bptbl_size); /** Detect all supported erase types * - * @param bptbl_ptr Pointer to memory holding a Basic Parameter Table structure - * @param smtbl All information parsed from the table gets passed back on this structure + * @param bptbl_ptr Pointer to memory holding a JEDEC Basic Flash Parameter Table + * @param[in,out] sfdp_info Contains the results of parsing erase type instructions and sizes * - * @return 0 on success, negative error code on failure + * @return MBED_SUCCESS on success, negative error code on failure */ int sfdp_detect_erase_types_inst_and_size(uint8_t *bptbl_ptr, sfdp_hdr_info &sfdp_info); +/** Find the region to which the given offset belongs to + * + * @param offset Offset value + * @param sfdp_info Region information + * + * @return Region number + */ +int sfdp_find_addr_region(bd_size_t offset, const sfdp_hdr_info &sfdp_info); + +/** Finds the largest Erase Type of the Region to which the offset belongs to + * + * Iterates from highest type to lowest. + * + * @param bitfield Erase types bit field + * @param size Upper limit for region size + * @param offset Offset value + * @param region Region number + * @param smtbl Information about different erase types + * + * @return Largest erase type + */ +int sfdp_iterate_next_largest_erase_type(uint8_t &bitfield, + int size, + int offset, + int region, + const sfdp_smptbl_info &smptbl); + /** @}*/ } /* namespace mbed */ #endif diff --git a/drivers/source/SFDP.cpp b/drivers/source/SFDP.cpp index 99ca5ba3f5..da240b0184 100644 --- a/drivers/source/SFDP.cpp +++ b/drivers/source/SFDP.cpp @@ -126,7 +126,7 @@ int sfdp_parse_single_param_header(sfdp_prm_hdr *phdr_ptr, sfdp_hdr_info &hdr_in return 0; } -int sfdp_parse_headers(Callback sfdp_reader, sfdp_hdr_info &hdr_info) +int sfdp_parse_headers(Callback sfdp_reader, sfdp_hdr_info &sfdp_info) { bd_addr_t addr = 0x0; int number_of_param_headers = 0; @@ -164,7 +164,7 @@ int sfdp_parse_headers(Callback sfdp_reader, return -1; } - hdr_status = sfdp_parse_single_param_header((sfdp_prm_hdr *)param_header, hdr_info); + hdr_status = sfdp_parse_single_param_header((sfdp_prm_hdr *)param_header, sfdp_info); if (hdr_status < 0) { return hdr_status; } @@ -295,7 +295,54 @@ int sfdp_detect_erase_types_inst_and_size(uint8_t *bptbl_ptr, sfdp_hdr_info &sfd return 0; } +int sfdp_find_addr_region(bd_size_t offset, const sfdp_hdr_info &sfdp_info) +{ + if ((offset > sfdp_info.bptbl.device_size_bytes) || (sfdp_info.smptbl.region_cnt == 0)) { + return -1; + } + if (sfdp_info.smptbl.region_cnt == 1) { + return 0; + } + + for (int i_ind = sfdp_info.smptbl.region_cnt - 2; i_ind >= 0; i_ind--) { + + if (offset > sfdp_info.smptbl.region_high_boundary[i_ind]) { + return (i_ind + 1); + } + } + return -1; + +} + +int sfdp_iterate_next_largest_erase_type(uint8_t &bitfield, + int size, + int offset, + int region, + const sfdp_smptbl_info &smptbl) +{ + 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)(smptbl.erase_type_size_arr[largest_erase_type])) && + ((smptbl.region_high_boundary[region] - offset) + > (int)(smptbl.erase_type_size_arr[largest_erase_type]))) { + break; + } else { + bitfield &= ~type_mask; + } + } + type_mask = type_mask >> 1; + } + + if (i_ind == 4) { + tr_error("No erase type was found for current region addr"); + } + return largest_erase_type; +} } /* namespace mbed */ #endif /* (DEVICE_SPI || DEVICE_QSPI) */