takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPIFBlockDevice.h Source File

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 */