Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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 "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 &sector_map_table_addr, size_t &sector_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 */