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
SPIFBlockDevice.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_SPIF_BLOCK_DEVICE_H 00017 #define MBED_SPIF_BLOCK_DEVICE_H 00018 00019 #include "platform/SingletonPtr.h" 00020 #include "drivers/SPI.h" 00021 #include "drivers/DigitalOut.h" 00022 #include "features/storage/blockdevice/BlockDevice.h" 00023 00024 /** Enum spif standard error codes 00025 * 00026 * @enum spif_bd_error 00027 */ 00028 enum spif_bd_error { 00029 SPIF_BD_ERROR_OK = 0, /*!< no error */ 00030 SPIF_BD_ERROR_DEVICE_ERROR = BD_ERROR_DEVICE_ERROR, /*!< device specific error -4001 */ 00031 SPIF_BD_ERROR_PARSING_FAILED = -4002, /* SFDP Parsing failed */ 00032 SPIF_BD_ERROR_READY_FAILED = -4003, /* Wait for Memory Ready failed */ 00033 SPIF_BD_ERROR_WREN_FAILED = -4004, /* Write Enable Failed */ 00034 SPIF_BD_ERROR_INVALID_ERASE_PARAMS = -4005, /* Erase command not on sector aligned addresses or exceeds device size */ 00035 }; 00036 00037 00038 #define SPIF_MAX_REGIONS 10 00039 #define MAX_NUM_OF_ERASE_TYPES 4 00040 00041 /** BlockDevice for SFDP based flash devices over SPI bus 00042 * 00043 * @code 00044 * // An example using SPI flash device on K82F target 00045 * #include "mbed.h" 00046 * #include "SPIFBlockDevice.h" 00047 * 00048 * // Create flash device on SPI bus with PTE5 as chip select 00049 * SPIFBlockDevice spif(PTE2, PTE4, PTE1, PTE5); 00050 * 00051 * int main() { 00052 * printf("spif test\n"); 00053 * 00054 * // Initialize the SPI flash device and print the memory layout 00055 * spif.init(); 00056 * printf("spif size: %llu\n", spif.size()); 00057 * printf("spif read size: %llu\n", spif.get_read_size()); 00058 * printf("spif program size: %llu\n", spif.get_program_size()); 00059 * printf("spif erase size: %llu\n", spif.get_erase_size()); 00060 * 00061 * // Write "Hello World!" to the first block 00062 * char *buffer = (char*)malloc(spif.get_erase_size()); 00063 * sprintf(buffer, "Hello World!\n"); 00064 * spif.erase(0, spif.get_erase_size()); 00065 * spif.program(buffer, 0, spif.get_erase_size()); 00066 * 00067 * // Read back what was stored 00068 * spif.read(buffer, 0, spif.get_erase_size()); 00069 * printf("%s", buffer); 00070 * 00071 * // Deinitialize the device 00072 * spif.deinit(); 00073 * } 00074 * @endcode 00075 */ 00076 class SPIFBlockDevice : public mbed::BlockDevice { 00077 public: 00078 /** Creates a SPIFBlockDevice on a SPI bus specified by pins 00079 * 00080 * @param mosi SPI master out, slave in pin 00081 * @param miso SPI master in, slave out pin 00082 * @param sclk SPI clock pin 00083 * @param csel SPI chip select pin 00084 * @param freq Clock speed of the SPI bus (defaults to 40MHz) 00085 */ 00086 SPIFBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName csel, int freq = 40000000); 00087 00088 /** Initialize a block device 00089 * 00090 * @return SPIF_BD_ERROR_OK(0) - success 00091 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed 00092 * SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out 00093 * SPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables 00094 */ 00095 virtual int init(); 00096 00097 /** Deinitialize a block device 00098 * 00099 * @return SPIF_BD_ERROR_OK(0) - success 00100 */ 00101 virtual int deinit(); 00102 00103 /** Desctruct SPIFBlockDevice 00104 */ 00105 ~SPIFBlockDevice() 00106 { 00107 deinit(); 00108 } 00109 00110 /** Read blocks from a block device 00111 * 00112 * @param buffer Buffer to write blocks to 00113 * @param addr Address of block to begin reading from 00114 * @param size Size to read in bytes, must be a multiple of read block size 00115 * @return SPIF_BD_ERROR_OK(0) - success 00116 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed 00117 */ 00118 virtual int read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size); 00119 00120 /** Program blocks to a block device 00121 * 00122 * @note The blocks must have been erased prior to being programmed 00123 * 00124 * @param buffer Buffer of data to write to blocks 00125 * @param addr Address of block to begin writing to 00126 * @param size Size to write in bytes, must be a multiple of program block size 00127 * @return SPIF_BD_ERROR_OK(0) - success 00128 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed 00129 * SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out 00130 * SPIF_BD_ERROR_WREN_FAILED - Write Enable failed 00131 */ 00132 virtual int program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size); 00133 00134 /** Erase blocks on a block device 00135 * 00136 * @note The state of an erased block is undefined until it has been programmed 00137 * 00138 * @param addr Address of block to begin erasing 00139 * @param size Size to erase in bytes, must be a multiple of erase block size 00140 * @return SPIF_BD_ERROR_OK(0) - success 00141 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed 00142 * SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out 00143 * SPIF_BD_ERROR_INVALID_ERASE_PARAMS - Trying to erase unaligned address or size 00144 */ 00145 virtual int erase(mbed::bd_addr_t addr, mbed::bd_size_t size); 00146 00147 /** Get the size of a readable block 00148 * 00149 * @return Size of a readable block in bytes 00150 */ 00151 virtual mbed::bd_size_t get_read_size() const; 00152 00153 /** Get the size of a programable block 00154 * 00155 * @return Size of a programable block in bytes 00156 * @note Must be a multiple of the read size 00157 */ 00158 virtual mbed::bd_size_t get_program_size() const; 00159 00160 /** Get the size of an erasable block 00161 * 00162 * @return Size of an erasable block in bytes 00163 * @note Must be a multiple of the program size 00164 */ 00165 virtual mbed::bd_size_t get_erase_size() const; 00166 00167 /** Get the size of minimal erasable sector size of given address 00168 * 00169 * @param addr Any address within block queried for erase sector size (can be any address within flash size offset) 00170 * @return Size of minimal erase sector size, in given address region, in bytes 00171 * @note Must be a multiple of the program size 00172 */ 00173 virtual mbed::bd_size_t get_erase_size(mbed::bd_addr_t addr) const; 00174 00175 /** Get the value of storage byte after it was erased 00176 * 00177 * If get_erase_value returns a non-negative byte value, the underlying 00178 * storage is set to that value when erased, and storage containing 00179 * that value can be programmed without another erase. 00180 * 00181 * @return The value of storage when erased, or -1 if you can't 00182 * rely on the value of erased storage 00183 */ 00184 virtual int get_erase_value() const; 00185 00186 /** Get the total size of the underlying device 00187 * 00188 * @return Size of the underlying device in bytes 00189 */ 00190 virtual mbed::bd_size_t size() const; 00191 00192 /** Get the BlockDevice class type. 00193 * 00194 * @return A string representation of the BlockDevice class type. 00195 */ 00196 virtual const char *get_type() const; 00197 00198 private: 00199 00200 // Internal functions 00201 00202 /****************************************/ 00203 /* SFDP Detection and Parsing Functions */ 00204 /****************************************/ 00205 // Parse SFDP Headers and retrieve Basic Param and Sector Map Tables (if exist) 00206 int _sfdp_parse_sfdp_headers(uint32_t &basic_table_addr, size_t &basic_table_size, 00207 uint32_t §or_map_table_addr, size_t §or_map_table_size); 00208 00209 // Parse and Detect required Basic Parameters from Table 00210 int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size); 00211 00212 // Parse and read information required by Regions Sector Map 00213 int _sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size); 00214 00215 // Detect fastest read Bus mode supported by device 00216 int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &read_inst); 00217 00218 // Set Page size for program 00219 unsigned int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size); 00220 00221 // Detect all supported erase types 00222 int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, 00223 int &erase4k_inst, 00224 int *erase_type_inst_arr, unsigned int *erase_type_size_arr); 00225 00226 /***********************/ 00227 /* Utilities Functions */ 00228 /***********************/ 00229 // Find the region to which the given offset belongs to 00230 int _utils_find_addr_region(bd_size_t offset) const; 00231 00232 // Iterate on all supported Erase Types of the Region to which the offset belongs to. 00233 // Iterates from highest type to lowest 00234 int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry); 00235 00236 /********************************/ 00237 /* Calls to SPI Driver APIs */ 00238 /********************************/ 00239 // Send Program => Write command to Driver 00240 spif_bd_error _spi_send_program_command(int prog_inst, const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size); 00241 00242 // Send Read command to Driver 00243 //spif_bd_error _spi_send_read_command(uint8_t read_inst, void *buffer, bd_addr_t addr, bd_size_t size); 00244 spif_bd_error _spi_send_read_command(int read_inst, uint8_t *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size); 00245 00246 // Send Erase Instruction using command_transfer command to Driver 00247 spif_bd_error _spi_send_erase_command(int erase_inst, mbed::bd_addr_t addr, mbed::bd_size_t size); 00248 00249 // Send Generic command_transfer command to Driver 00250 spif_bd_error _spi_send_general_command(int instruction, mbed::bd_addr_t addr, char *tx_buffer, 00251 size_t tx_length, char *rx_buffer, size_t rx_length); 00252 00253 // Send set_frequency command to Driver 00254 spif_bd_error _spi_set_frequency(int freq); 00255 /********************************/ 00256 00257 // Soft Reset Flash Memory 00258 int _reset_flash_mem(); 00259 00260 // Configure Write Enable in Status Register 00261 int _set_write_enable(); 00262 00263 // Wait on status register until write not-in-progress 00264 bool _is_mem_ready(); 00265 00266 private: 00267 // Master side hardware 00268 mbed::SPI _spi; 00269 // Enable CS control (low/high) for SPI driver operations 00270 mbed::DigitalOut _cs; 00271 00272 // Mutex is used to protect Flash device for some SPI Driver commands that must be done sequentially with no other commands in between 00273 // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready 00274 static SingletonPtr<PlatformMutex> _mutex; 00275 00276 // Command Instructions 00277 int _read_instruction; 00278 int _prog_instruction; 00279 int _erase_instruction; 00280 int _erase4k_inst; // Legacy 4K erase instruction (default 0x20h) 00281 00282 // Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size) 00283 int _erase_type_inst_arr[MAX_NUM_OF_ERASE_TYPES]; 00284 unsigned int _erase_type_size_arr[MAX_NUM_OF_ERASE_TYPES]; 00285 00286 // Sector Regions Map 00287 int _regions_count; //number of regions 00288 int _region_size_bytes[SPIF_MAX_REGIONS]; //regions size in bytes 00289 bd_size_t _region_high_boundary[SPIF_MAX_REGIONS]; //region high address offset boundary 00290 //Each Region can support a bit combination of any of the 4 Erase Types 00291 uint8_t _region_erase_types_bitfield[SPIF_MAX_REGIONS]; 00292 unsigned int _min_common_erase_size; // minimal common erase size for all regions (0 if none exists) 00293 00294 unsigned int _page_size_bytes; // Page size - 256 Bytes default 00295 bd_size_t _device_size_bytes; 00296 00297 // Bus configuration 00298 unsigned int _address_size; // number of bytes for address 00299 unsigned int _read_dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Read Bus Mode 00300 unsigned int _write_dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Write Bus Mode 00301 unsigned int _dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Current Bus Mode 00302 uint32_t _init_ref_count; 00303 bool _is_initialized; 00304 }; 00305 00306 #endif /* MBED_SPIF_BLOCK_DEVICE_H */
Generated on Tue Jul 12 2022 13:54:51 by
1.7.2