Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
QSPIFBlockDevice.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2018 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #ifndef MBED_QSPIF_BLOCK_DEVICE_H 00017 #define MBED_QSPIF_BLOCK_DEVICE_H 00018 00019 #include "drivers/QSPI.h" 00020 #include "features/storage/blockdevice/BlockDevice.h" 00021 00022 /** Enum qspif standard error codes 00023 * 00024 * @enum qspif_bd_error 00025 */ 00026 enum qspif_bd_error { 00027 QSPIF_BD_ERROR_OK = 0, /*!< no error */ 00028 QSPIF_BD_ERROR_DEVICE_ERROR = BD_ERROR_DEVICE_ERROR, /*!< device specific error -4001 */ 00029 QSPIF_BD_ERROR_PARSING_FAILED = -4002, /* SFDP Parsing failed */ 00030 QSPIF_BD_ERROR_READY_FAILED = -4003, /* Wait for Mem Ready failed */ 00031 QSPIF_BD_ERROR_WREN_FAILED = -4004, /* Write Enable Failed */ 00032 QSPIF_BD_ERROR_INVALID_ERASE_PARAMS = -4005, /* Erase command not on sector aligned addresses or exceeds device size */ 00033 QSPIF_BD_ERROR_DEVICE_NOT_UNIQUE = -4006, /* Only one instance per csel is allowed */ 00034 QSPIF_BD_ERROR_DEVICE_MAX_EXCEED = -4007 /* Max active QSPIF devices exceeded */ 00035 }; 00036 00037 /** Enum qspif polarity mode 00038 * 00039 * @enum qspif_polarity_mode 00040 */ 00041 enum qspif_polarity_mode { 00042 QSPIF_POLARITY_MODE_0 = 0, /* CPOL=0, CPHA=0 */ 00043 QSPIF_POLARITY_MODE_1 /* CPOL=1, CPHA=1 */ 00044 }; 00045 00046 #define QSPIF_MAX_REGIONS 10 00047 #define MAX_NUM_OF_ERASE_TYPES 4 00048 #define QSPIF_MAX_ACTIVE_FLASH_DEVICES 10 00049 00050 /** BlockDevice for SFDP based flash devices over QSPI bus 00051 * 00052 * @code 00053 * // Here's an example using QSPI flash device on DISCO_L476VG target 00054 * #include "mbed.h" 00055 * #include "QSPIFBlockDevice.h" 00056 * 00057 * QSPIFBlockDevice block_device(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3, 00058 * QSPI_FLASH1_SCK, QSPI_FLASH1_CSN, QSPIF_POLARITY_MODE_0, MBED_CONF_QSPIF_QSPI_FREQ); 00059 * 00060 * int main() 00061 * { 00062 * printf("QSPI SFDP Flash Block Device example\n"); 00063 * 00064 * // Initialize the SPI flash device and print the memory layout 00065 * block_device.init(); 00066 * bd_size_t sector_size_at_address_0 = block_device.get_erase_size(0); 00067 * 00068 * printf("QSPIF BD size: %llu\n", block_device.size()); 00069 * printf("QSPIF BD read size: %llu\n", block_device.get_read_size()); 00070 * printf("QSPIF BD program size: %llu\n", block_device.get_program_size()); 00071 * printf("QSPIF BD erase size (at address 0): %llu\n", sector_size_at_address_0); 00072 * 00073 * // Write "Hello World!" to the first block 00074 * char *buffer = (char *) malloc(sector_size_at_address_0); 00075 * sprintf(buffer, "Hello World!\n"); 00076 * block_device.erase(0, sector_size_at_address_0); 00077 * block_device.program(buffer, 0, sector_size_at_address_0); 00078 * 00079 * // Read back what was stored 00080 * block_device.read(buffer, 0, sector_size_at_address_0); 00081 * printf("%s", buffer); 00082 * 00083 * // Deinitialize the device 00084 * block_device.deinit(); 00085 * } 00086 * @endcode 00087 */ 00088 class QSPIFBlockDevice : public mbed::BlockDevice { 00089 public: 00090 /** Create QSPIFBlockDevice - An SFDP based Flash Block Device over QSPI bus 00091 * 00092 * @param io0 1st IO pin used for sending/receiving data during data phase of a transaction 00093 * @param io1 2nd IO pin used for sending/receiving data during data phase of a transaction 00094 * @param io2 3rd IO pin used for sending/receiving data during data phase of a transaction 00095 * @param io3 4th IO pin used for sending/receiving data during data phase of a transaction 00096 * @param sclk QSPI Clock pin 00097 * @param csel QSPI chip select pin 00098 * @param clock_mode specifies the QSPI Clock Polarity mode (QSPIF_POLARITY_MODE_0/QSPIF_POLARITY_MODE_1) 00099 * default value = 0 00100 * @param freq Clock frequency of the QSPI bus (defaults to 40MHz) 00101 * 00102 */ 00103 QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel, 00104 int clock_mode, int freq = MBED_CONF_QSPIF_QSPI_FREQ); 00105 00106 /** Initialize a block device 00107 * 00108 * @return QSPIF_BD_ERROR_OK(0) - success 00109 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed 00110 * QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timedout 00111 * QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables 00112 */ 00113 virtual int init(); 00114 00115 /** Deinitialize a block device 00116 * 00117 * @return QSPIF_BD_ERROR_OK(0) - success 00118 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed 00119 */ 00120 virtual int deinit(); 00121 00122 /** Desctruct QSPIFBlockDevie 00123 */ 00124 ~QSPIFBlockDevice() 00125 { 00126 deinit(); 00127 } 00128 00129 /** Read blocks from a block device 00130 * 00131 * @param buffer Buffer to write blocks to 00132 * @param addr Address of block to begin reading from 00133 * @param size Size to read in bytes, must be a multiple of read block size 00134 * @return QSPIF_BD_ERROR_OK(0) - success 00135 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed 00136 */ 00137 virtual int read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size); 00138 00139 /** Program blocks to a block device 00140 * 00141 * The blocks must have been erased prior to being programmed 00142 * 00143 * @param buffer Buffer of data to write to blocks 00144 * @param addr Address of block to begin writing to 00145 * @param size Size to write in bytes, must be a multiple of program block size 00146 * @return QSPIF_BD_ERROR_OK(0) - success 00147 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed 00148 * QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out 00149 * QSPIF_BD_ERROR_WREN_FAILED - Write Enable failed 00150 * QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables 00151 */ 00152 virtual int program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size); 00153 00154 /** Erase blocks on a block device 00155 * 00156 * The state of an erased block is undefined until it has been programmed 00157 * 00158 * @param addr Address of block to begin erasing 00159 * @param size Size to erase in bytes, must be a multiple of erase block size 00160 * @return QSPIF_BD_ERROR_OK(0) - success 00161 * QSPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed 00162 * QSPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out 00163 * QSPIF_BD_ERROR_WREN_FAILED - Write Enable failed 00164 * QSPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables 00165 * QSPIF_BD_ERROR_INVALID_ERASE_PARAMS - Trying to erase unaligned address or size 00166 */ 00167 virtual int erase(mbed::bd_addr_t addr, mbed::bd_size_t size); 00168 00169 /** Get the size of a readable block 00170 * 00171 * @return Size of a readable block in bytes 00172 */ 00173 virtual mbed::bd_size_t get_read_size() const; 00174 00175 /** Get the size of a programable block 00176 * 00177 * @return Size of a program block size in bytes 00178 * @note Must be a multiple of the read size 00179 */ 00180 virtual mbed::bd_size_t get_program_size() const; 00181 00182 /** Get the size of a eraseable block 00183 * 00184 * @return Size of a minimal erase block, common to all regions, in bytes 00185 * @note Must be a multiple of the program size 00186 */ 00187 virtual mbed::bd_size_t get_erase_size() const; 00188 00189 /** Get the size of minimal eraseable sector size of given address 00190 * 00191 * @param addr Any address within block queried for erase sector size (can be any address within flash size offset) 00192 * @return Size of minimal erase sector size, in given address region, in bytes 00193 * @note Must be a multiple of the program size 00194 */ 00195 virtual mbed::bd_size_t get_erase_size(mbed::bd_addr_t addr); 00196 00197 /** Get the value of storage byte after it was erased 00198 * 00199 * If get_erase_value returns a non-negative byte value, the underlying 00200 * storage is set to that value when erased, and storage containing 00201 * that value can be programmed without another erase. 00202 * 00203 * @return The value of storage when erased, or -1 if you can't 00204 * rely on the value of erased storage 00205 */ 00206 virtual int get_erase_value() const; 00207 00208 /** Get the total size of the underlying device 00209 * 00210 * @return Size of the underlying device in bytes 00211 */ 00212 virtual mbed::bd_size_t size() const; 00213 00214 /** Get the BlockDevice class type. 00215 * 00216 * @return A string represent the BlockDevice class type. 00217 */ 00218 virtual const char *get_type() const; 00219 00220 private: 00221 // Internal functions 00222 00223 00224 /********************************/ 00225 /* Different Device Csel Mgmt */ 00226 /********************************/ 00227 // Add a new QSPI device CS to existing devices list. 00228 // Only one QSPIFBlockDevice instance per CS is allowed 00229 int add_new_csel_instance(PinName csel); 00230 00231 // Remove device CS from existing device list upon destroying object (last deinit is called) 00232 int remove_csel_instance(PinName csel); 00233 00234 /********************************/ 00235 /* Calls to QSPI Driver APIs */ 00236 /********************************/ 00237 // Send Program/Write command to Driver 00238 qspi_status_t _qspi_send_program_command(mbed::qspi_inst_t prog_instruction, const void *buffer, 00239 mbed::bd_addr_t addr, mbed::bd_size_t *size); 00240 00241 // Send Read command to Driver 00242 qspi_status_t _qspi_send_read_command(mbed::qspi_inst_t read_instruction, void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size); 00243 00244 // Send Erase Instruction using command_transfer command to Driver 00245 qspi_status_t _qspi_send_erase_command(mbed::qspi_inst_t erase_instruction, mbed::bd_addr_t addr, mbed::bd_size_t size); 00246 00247 // Send Generic command_transfer command to Driver 00248 qspi_status_t _qspi_send_general_command(mbed::qspi_inst_t instruction_int, mbed::bd_addr_t addr, const char *tx_buffer, 00249 mbed::bd_size_t tx_length, const char *rx_buffer, mbed::bd_size_t rx_length); 00250 00251 // Send command to read from the SFDP table 00252 qspi_status_t _qspi_send_read_sfdp_command(mbed::bd_addr_t addr, void *rx_buffer, mbed::bd_size_t rx_length); 00253 00254 // Read the contents of status registers 1 and 2 into a buffer (buffer must have a length of 2) 00255 qspi_status_t _qspi_read_status_registers(uint8_t *reg_buffer); 00256 00257 // Set the contents of status registers 1 and 2 from a buffer (buffer must have a length of 2) 00258 qspi_status_t _qspi_write_status_registers(uint8_t *reg_buffer); 00259 00260 // Send set_frequency command to Driver 00261 qspi_status_t _qspi_set_frequency(int freq); 00262 00263 // Update the 4-byte addressing extension register with the MSB of the address if it is in use 00264 qspi_status_t _qspi_update_4byte_ext_addr_reg(bd_addr_t addr); 00265 00266 /*********************************/ 00267 /* Flash Configuration Functions */ 00268 /*********************************/ 00269 // Clear the device's block protection 00270 int _clear_block_protection(); 00271 00272 // Configure Write Enable in Status Register 00273 int _set_write_enable(); 00274 00275 // Wait on status register until write not-in-progress 00276 bool _is_mem_ready(); 00277 00278 // Enable Fast Mode - for flash chips with low power default 00279 int _enable_fast_mode(); 00280 00281 /****************************************/ 00282 /* SFDP Detection and Parsing Functions */ 00283 /****************************************/ 00284 // Parse SFDP Headers and retrieve Basic Param and Sector Map Tables (if exist) 00285 int _sfdp_parse_sfdp_headers(uint32_t &basic_table_addr, size_t &basic_table_size, 00286 uint32_t §or_map_table_addr, size_t §or_map_table_size); 00287 00288 // Parse and Detect required Basic Parameters from Table 00289 int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size); 00290 00291 // Parse and read information required by Regions Sector Map 00292 int _sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size); 00293 00294 // Detect the soft reset protocol and reset - returns error if soft reset is not supported 00295 int _sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param_table_ptr); 00296 00297 // Detect fastest read Bus mode supported by device 00298 int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, 00299 bool &set_quad_enable, bool &is_qpi_mode); 00300 00301 // Enable Quad mode if supported (1-1-4, 1-4-4, 4-4-4 bus modes) 00302 int _sfdp_set_quad_enabled(uint8_t *basic_param_table_ptr); 00303 00304 // Enable QPI mode (4-4-4) 00305 int _sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr); 00306 00307 // Set Page size for program 00308 int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size); 00309 00310 // Detect all supported erase types 00311 int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size); 00312 00313 // Detect 4-byte addressing mode and enable it if supported 00314 int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size); 00315 00316 // Query vendor ID and handle special behavior that isn't covered by SFDP data 00317 int _handle_vendor_quirks(); 00318 00319 /***********************/ 00320 /* Utilities Functions */ 00321 /***********************/ 00322 // Find the region to which the given offset belong to 00323 int _utils_find_addr_region(mbed::bd_size_t offset); 00324 00325 // Iterate on all supported Erase Types of the Region to which the offset belong to. 00326 // Iterates from highest type to lowest 00327 int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry); 00328 00329 private: 00330 enum qspif_clear_protection_method_t { 00331 QSPIF_BP_ULBPR, // Issue global protection unlock instruction 00332 QSPIF_BP_CLEAR_SR, // Clear protection bits in status register 1 00333 }; 00334 00335 // QSPI Driver Object 00336 mbed::QSPI _qspi; 00337 00338 // Static List of different QSPI based Flash devices csel that already exist 00339 // Each QSPI Flash device csel can have only 1 QSPIFBlockDevice instance 00340 // _devices_mutex is used to lock csel list - only one QSPIFBlockDevice instance per csel is allowed 00341 static SingletonPtr<PlatformMutex> _devices_mutex; 00342 static int _number_of_active_qspif_flash_csel; 00343 static PinName *_active_qspif_flash_csel_arr; 00344 00345 int _unique_device_status; 00346 PinName _csel; 00347 00348 // Mutex is used to protect Flash device for some QSPI Driver commands that must be done sequentially with no other commands in between 00349 // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready 00350 PlatformMutex _mutex; 00351 00352 // Command Instructions 00353 mbed::qspi_inst_t _read_instruction; 00354 mbed::qspi_inst_t _legacy_erase_instruction; 00355 00356 // Status register write/read instructions 00357 unsigned int _num_status_registers; 00358 mbed::qspi_inst_t _write_status_reg_2_inst; 00359 mbed::qspi_inst_t _read_status_reg_2_inst; // If three registers, this instruction reads the latter two 00360 00361 // Attempt to enable 4-byte addressing. True by default, but may be disabled for some vendors 00362 bool _attempt_4_byte_addressing; 00363 // 4-byte addressing extension register write instruction 00364 mbed::qspi_inst_t _4byte_msb_reg_write_inst; 00365 00366 // Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size) 00367 mbed::qspi_inst_t _erase_type_inst_arr[MAX_NUM_OF_ERASE_TYPES]; 00368 unsigned int _erase_type_size_arr[MAX_NUM_OF_ERASE_TYPES]; 00369 00370 // Quad mode enable status register and bit 00371 int _quad_enable_register_idx; 00372 int _quad_enable_bit; 00373 00374 bool _needs_fast_mode; 00375 00376 // Clear block protection 00377 qspif_clear_protection_method_t _clear_protection_method; 00378 00379 // Sector Regions Map 00380 int _regions_count; //number of regions 00381 int _region_size_bytes[QSPIF_MAX_REGIONS]; //regions size in bytes 00382 bd_size_t _region_high_boundary[QSPIF_MAX_REGIONS]; //region high address offset boundary 00383 //Each Region can support a bit combination of any of the 4 Erase Types 00384 uint8_t _region_erase_types_bitfield[QSPIF_MAX_REGIONS]; 00385 unsigned int _min_common_erase_size; // minimal common erase size for all regions (0 if none exists) 00386 00387 unsigned int _page_size_bytes; // Page size - 256 Bytes default 00388 int _freq; 00389 bd_size_t _device_size_bytes; 00390 00391 // Bus speed configuration 00392 qspi_bus_width_t _inst_width; //Bus width for Instruction phase 00393 qspi_bus_width_t _address_width; //Bus width for Address phase 00394 qspi_address_size_t _address_size; //Number of bits for address 00395 qspi_alt_size_t _alt_size; //Number of bits for alt 00396 bool _alt_enabled; //Whether alt is enabled 00397 uint8_t _dummy_cycles; //Number of Dummy cycles required by Current Bus Mode 00398 qspi_bus_width_t _data_width; //Bus width for Data phase 00399 00400 uint32_t _init_ref_count; 00401 bool _is_initialized; 00402 }; 00403 00404 #endif
Generated on Tue Jul 12 2022 13:54:46 by
