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() 00105 { 00106 deinit(); 00107 } 00108 00109 /** Read blocks from a block device 00110 * 00111 * @param buffer Buffer to write blocks to 00112 * @param addr Address of block to begin reading from 00113 * @param size Size to read in bytes, must be a multiple of read block size 00114 * @return SPIF_BD_ERROR_OK(0) - success 00115 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed 00116 */ 00117 virtual int read(void *buffer, bd_addr_t addr, bd_size_t size); 00118 00119 /** Program blocks to a block device 00120 * 00121 * The blocks must have been erased prior to being programmed 00122 * 00123 * @param buffer Buffer of data to write to blocks 00124 * @param addr Address of block to begin writing to 00125 * @param size Size to write in bytes, must be a multiple of program block size 00126 * @return SPIF_BD_ERROR_OK(0) - success 00127 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed 00128 * SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out 00129 * SPIF_BD_ERROR_WREN_FAILED - Write Enable failed 00130 */ 00131 virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size); 00132 00133 /** Erase blocks on a block device 00134 * 00135 * The state of an erased block is undefined until it has been programmed 00136 * 00137 * @param addr Address of block to begin erasing 00138 * @param size Size to erase in bytes, must be a multiple of erase block size 00139 * @return SPIF_BD_ERROR_OK(0) - success 00140 * SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed 00141 * SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out 00142 * SPIF_BD_ERROR_WREN_FAILED - Write Enable failed 00143 * SPIF_BD_ERROR_INVALID_ERASE_PARAMS - Trying to erase unaligned address or size 00144 */ 00145 virtual int erase(bd_addr_t addr, 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 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 bd_size_t get_program_size() const; 00159 00160 /** Get the size of a eraseable block 00161 * 00162 * @return Size of a eraseable block in bytes 00163 * @note Must be a multiple of the program size 00164 */ 00165 virtual bd_size_t get_erase_size() const; 00166 00167 /** Get the size of minimal eraseable 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 bd_size_t get_erase_size(bd_addr_t addr); 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 bd_size_t size() const; 00191 00192 private: 00193 00194 // Internal functions 00195 00196 /****************************************/ 00197 /* SFDP Detection and Parsing Functions */ 00198 /****************************************/ 00199 // Parse SFDP Headers and retrieve Basic Param and Sector Map Tables (if exist) 00200 int _sfdp_parse_sfdp_headers(uint32_t &basic_table_addr, size_t &basic_table_size, 00201 uint32_t §or_map_table_addr, size_t §or_map_table_size); 00202 00203 // Parse and Detect required Basic Parameters from Table 00204 int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size); 00205 00206 // Parse and read information required by Regions Secotr Map 00207 int _sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size); 00208 00209 // Detect fastest read Bus mode supported by device 00210 int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &read_inst); 00211 00212 // Set Page size for program 00213 unsigned int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size); 00214 00215 // Detect all supported erase types 00216 int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size, 00217 int &erase4k_inst, 00218 int *erase_type_inst_arr, unsigned int *erase_type_size_arr); 00219 00220 /***********************/ 00221 /* Utilities Functions */ 00222 /***********************/ 00223 // Find the region to which the given offset belong to 00224 int _utils_find_addr_region(bd_size_t offset); 00225 00226 // Iterate on all supported Erase Types of the Region to which the offset belong to. 00227 // Iterates from highest type to lowest 00228 int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry); 00229 00230 /********************************/ 00231 /* Calls to SPI Driver APIs */ 00232 /********************************/ 00233 // Send Program => Write command to Driver 00234 spif_bd_error _spi_send_program_command(int prog_inst, const void *buffer, bd_addr_t addr, bd_size_t size); 00235 00236 // Send Read command to Driver 00237 //spif_bd_error _spi_send_read_command(uint8_t read_inst, void *buffer, bd_addr_t addr, bd_size_t size); 00238 spif_bd_error _spi_send_read_command(int read_inst, uint8_t *buffer, bd_addr_t addr, bd_size_t size); 00239 00240 // Send Erase Instruction using command_transfer command to Driver 00241 spif_bd_error _spi_send_erase_command(int erase_inst, bd_addr_t addr, bd_size_t size); 00242 00243 // Send Generic command_transfer command to Driver 00244 spif_bd_error _spi_send_general_command(int instruction, bd_addr_t addr, char *tx_buffer, 00245 size_t tx_length, char *rx_buffer, size_t rx_length); 00246 00247 // Send set_frequency command to Driver 00248 spif_bd_error _spi_set_frequency(int freq); 00249 /********************************/ 00250 00251 // Soft Reset Flash Memory 00252 int _reset_flash_mem(); 00253 00254 // Configure Write Enable in Status Register 00255 int _set_write_enable(); 00256 00257 // Wait on status register until write not-in-progress 00258 bool _is_mem_ready(); 00259 00260 private: 00261 // Master side hardware 00262 mbed::SPI _spi; 00263 // Enable CS control (low/high) for SPI driver operatios 00264 mbed::DigitalOut _cs; 00265 00266 // Mutex is used to protect Flash device for some SPI Driver commands that must be done sequentially with no other commands in between 00267 // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready 00268 static SingletonPtr<PlatformMutex> _mutex; 00269 00270 // Command Instructions 00271 int _read_instruction; 00272 int _prog_instruction; 00273 int _erase_instruction; 00274 int _erase4k_inst; // Legacy 4K erase instruction (default 0x20h) 00275 00276 // Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size) 00277 int _erase_type_inst_arr[MAX_NUM_OF_ERASE_TYPES]; 00278 unsigned int _erase_type_size_arr[MAX_NUM_OF_ERASE_TYPES]; 00279 00280 // Sector Regions Map 00281 int _regions_count; //number of regions 00282 int _region_size_bytes[SPIF_MAX_REGIONS]; //regions size in bytes 00283 bd_size_t _region_high_boundary[SPIF_MAX_REGIONS]; //region high address offset boundary 00284 //Each Region can support a bit combination of any of the 4 Erase Types 00285 uint8_t _region_erase_types_bitfield[SPIF_MAX_REGIONS]; 00286 unsigned int _min_common_erase_size; // minimal common erase size for all regions (0 if none exists) 00287 00288 unsigned int _page_size_bytes; // Page size - 256 Bytes default 00289 bd_size_t _device_size_bytes; 00290 00291 // Bus configuration 00292 unsigned int _address_size; // number of bytes for address 00293 unsigned int _read_dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Read Bus Mode 00294 unsigned int _write_dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Write Bus Mode 00295 unsigned int _dummy_and_mode_cycles; // Number of Dummy and Mode Bits required by Current Bus Mode 00296 uint32_t _init_ref_count; 00297 bool _is_initialized; 00298 }; 00299 00300 #endif /* MBED_SPIF_BLOCK_DEVICE_H */
Generated on Tue Jul 12 2022 20:52:57 by
1.7.2