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