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.cpp Source File

SPIFBlockDevice.cpp

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 
00017 #include "SPIFBlockDevice.h"
00018 #include "rtos/ThisThread.h"
00019 #include "mbed_critical.h"
00020 
00021 #include <string.h>
00022 #include <inttypes.h>
00023 
00024 #include "mbed_trace.h"
00025 #define TRACE_GROUP "SPIF"
00026 using namespace mbed;
00027 
00028 /* Default SPIF Parameters */
00029 /****************************/
00030 #define SPIF_DEFAULT_READ_SIZE  1
00031 #define SPIF_DEFAULT_PROG_SIZE  1
00032 #define SPIF_DEFAULT_PAGE_SIZE  256
00033 #define SPIF_DEFAULT_SE_SIZE    4096
00034 #define SPI_MAX_STATUS_REGISTER_SIZE 2
00035 #ifndef UINT64_MAX
00036 #define UINT64_MAX -1
00037 #endif
00038 #define SPI_NO_ADDRESS_COMMAND UINT64_MAX
00039 // Status Register Bits
00040 #define SPIF_STATUS_BIT_WIP 0x1 //Write In Progress
00041 #define SPIF_STATUS_BIT_WEL 0x2 // Write Enable Latch
00042 
00043 /* SFDP Header Parsing */
00044 /***********************/
00045 #define SPIF_SFDP_HEADER_SIZE 8
00046 #define SPIF_PARAM_HEADER_SIZE 8
00047 
00048 /* Basic Parameters Table Parsing */
00049 /**********************************/
00050 #define SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES 64 /* 16 DWORDS */
00051 //READ Instruction support according to BUS Configuration
00052 #define SPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE 2
00053 #define SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE 16
00054 #define SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23
00055 #define SPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15
00056 #define SPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13
00057 #define SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE 40
00058 // Address Length
00059 #define SPIF_ADDR_SIZE_3_BYTES 3
00060 #define SPIF_ADDR_SIZE_4_BYTES 4
00061 // Erase Types Params
00062 #define SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE 29
00063 #define SPIF_BASIC_PARAM_ERASE_TYPE_2_BYTE 31
00064 #define SPIF_BASIC_PARAM_ERASE_TYPE_3_BYTE 33
00065 #define SPIF_BASIC_PARAM_ERASE_TYPE_4_BYTE 35
00066 #define SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE 28
00067 #define SPIF_BASIC_PARAM_ERASE_TYPE_2_SIZE_BYTE 30
00068 #define SPIF_BASIC_PARAM_ERASE_TYPE_3_SIZE_BYTE 32
00069 #define SPIF_BASIC_PARAM_ERASE_TYPE_4_SIZE_BYTE 34
00070 #define SPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1
00071 
00072 // Erase Types Per Region BitMask
00073 #define ERASE_BITMASK_TYPE4 0x08
00074 #define ERASE_BITMASK_TYPE1 0x01
00075 #define ERASE_BITMASK_NONE  0x00
00076 #define ERASE_BITMASK_ALL   0x0F
00077 
00078 #define IS_MEM_READY_MAX_RETRIES 10000
00079 
00080 enum spif_default_instructions {
00081     SPIF_NOP = 0x00, // No operation
00082     SPIF_PP = 0x02, // Page Program data
00083     SPIF_READ = 0x03, // Read data
00084     SPIF_SE   = 0x20, // 4KB Sector Erase
00085     SPIF_SFDP = 0x5a, // Read SFDP
00086     SPIF_WRSR = 0x01, // Write Status/Configuration Register
00087     SPIF_WRDI = 0x04, // Write Disable
00088     SPIF_RDSR = 0x05, // Read Status Register
00089     SPIF_WREN = 0x06, // Write Enable
00090     SPIF_RSTEN = 0x66, // Reset Enable
00091     SPIF_RST = 0x99, // Reset
00092     SPIF_RDID = 0x9f, // Read Manufacturer and JDEC Device ID
00093     SPIF_ULBPR = 0x98, // Clears all write-protection bits in the Block-Protection register,
00094     SPIF_4BEN = 0xB7, // Enable 4-byte address mode
00095     SPIF_4BDIS = 0xE9, // Disable 4-byte address mode
00096 };
00097 
00098 // Mutex is used for some SPI Driver commands that must be done sequentially with no other commands in between
00099 // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
00100 SingletonPtr<PlatformMutex>  SPIFBlockDevice::_mutex;
00101 
00102 // Local Function
00103 static unsigned int local_math_power(int base, int exp);
00104 
00105 //***********************
00106 // SPIF Block Device APIs
00107 //***********************
00108 SPIFBlockDevice::SPIFBlockDevice(
00109     PinName mosi, PinName miso, PinName sclk, PinName csel, int freq)
00110     : _spi(mosi, miso, sclk), _cs(csel), _read_instruction(0), _prog_instruction(0), _erase_instruction(0),
00111       _erase4k_inst(0), _page_size_bytes(0), _device_size_bytes(0), _init_ref_count(0), _is_initialized(false)
00112 {
00113     _address_size = SPIF_ADDR_SIZE_3_BYTES;
00114     // Initial SFDP read tables are read with 8 dummy cycles
00115     // Default Bus Setup 1_1_1 with 0 dummy and mode cycles
00116     _read_dummy_and_mode_cycles = 8;
00117     _write_dummy_and_mode_cycles = 0;
00118     _dummy_and_mode_cycles = _read_dummy_and_mode_cycles;
00119 
00120     _min_common_erase_size = 0;
00121     _regions_count = 1;
00122     _region_erase_types_bitfield[0] = ERASE_BITMASK_NONE;
00123 
00124     if (SPIF_BD_ERROR_OK != _spi_set_frequency(freq)) {
00125         tr_error("SPI Set Frequency Failed");
00126     }
00127 
00128     _cs = 1;
00129 }
00130 
00131 int SPIFBlockDevice::init()
00132 {
00133     uint8_t vendor_device_ids[4];
00134     size_t data_length = 3;
00135     int status = SPIF_BD_ERROR_OK;
00136     uint32_t basic_table_addr = 0;
00137     size_t basic_table_size = 0;
00138     uint32_t sector_map_table_addr = 0;
00139     size_t sector_map_table_size = 0;
00140     spif_bd_error spi_status = SPIF_BD_ERROR_OK;
00141 
00142     _mutex->lock();
00143 
00144     if (!_is_initialized) {
00145         _init_ref_count = 0;
00146     }
00147 
00148     _init_ref_count++;
00149 
00150     if (_init_ref_count != 1) {
00151         goto exit_point;
00152     }
00153 
00154     // Soft Reset
00155     if (-1 == _reset_flash_mem()) {
00156         tr_error("init - Unable to initialize flash memory, tests failed");
00157         status = SPIF_BD_ERROR_DEVICE_ERROR;
00158         goto exit_point;
00159     } else {
00160         tr_debug("Initialize flash memory OK");
00161     }
00162 
00163     /* Read Manufacturer ID (1byte), and Device ID (2bytes)*/
00164     spi_status = _spi_send_general_command(SPIF_RDID, SPI_NO_ADDRESS_COMMAND, NULL, 0, (char *)vendor_device_ids,
00165                                            data_length);
00166     if (spi_status != SPIF_BD_ERROR_OK) {
00167         tr_error("init - Read Vendor ID Failed");
00168         status = SPIF_BD_ERROR_DEVICE_ERROR;
00169         goto exit_point;
00170     }
00171 
00172     switch (vendor_device_ids[0]) {
00173         case 0xbf:
00174             // SST devices come preset with block protection
00175             // enabled for some regions, issue global protection unlock to clear
00176             _set_write_enable();
00177             _spi_send_general_command(SPIF_ULBPR, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
00178             break;
00179     }
00180 
00181     //Synchronize Device
00182     if (false == _is_mem_ready()) {
00183         tr_error("init - _is_mem_ready Failed");
00184         status = SPIF_BD_ERROR_READY_FAILED;
00185         goto exit_point;
00186     }
00187 
00188     /**************************** Parse SFDP Header ***********************************/
00189     if (0 != _sfdp_parse_sfdp_headers(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) {
00190         tr_error("init - Parse SFDP Headers Failed");
00191         status = SPIF_BD_ERROR_PARSING_FAILED;
00192         goto exit_point;
00193     }
00194 
00195 
00196     /**************************** Parse Basic Parameters Table ***********************************/
00197     if (0 != _sfdp_parse_basic_param_table(basic_table_addr, basic_table_size)) {
00198         tr_error("init - Parse Basic Param Table Failed");
00199         status = SPIF_BD_ERROR_PARSING_FAILED;
00200         goto exit_point;
00201     }
00202 
00203     /**************************** Parse Sector Map Table ***********************************/
00204     _region_size_bytes[0] =
00205         _device_size_bytes; // If there's no region map, we have a single region sized the entire device size
00206     _region_high_boundary[0] = _device_size_bytes - 1;
00207 
00208     if ((sector_map_table_addr != 0) && (0 != sector_map_table_size)) {
00209         tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", sector_map_table_addr,
00210                  sector_map_table_size);
00211         if (0 != _sfdp_parse_sector_map_table(sector_map_table_addr, sector_map_table_size)) {
00212             tr_error("init - Parse Sector Map Table Failed");
00213             status = SPIF_BD_ERROR_PARSING_FAILED;
00214             goto exit_point;
00215         }
00216     }
00217 
00218     // Configure  BUS Mode to 1_1_1 for all commands other than Read
00219     // Dummy And Mode Cycles Back default 0
00220     _dummy_and_mode_cycles = _write_dummy_and_mode_cycles;
00221     _is_initialized = true;
00222     tr_debug("Device size: %llu Kbytes", _device_size_bytes / 1024);
00223 
00224     if (_device_size_bytes > (1 << 24)) {
00225         tr_debug("Size is bigger than 16MB and thus address does not fit in 3 byte, switch to 4 byte address mode");
00226         _spi_send_general_command(SPIF_4BEN, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
00227         _address_size = SPIF_ADDR_SIZE_4_BYTES;
00228     }
00229 
00230 exit_point:
00231     _mutex->unlock();
00232 
00233     return status;
00234 }
00235 
00236 
00237 int SPIFBlockDevice::deinit()
00238 {
00239     spif_bd_error status = SPIF_BD_ERROR_OK;
00240 
00241     _mutex->lock();
00242 
00243     if (!_is_initialized) {
00244         _init_ref_count = 0;
00245         goto exit_point;
00246     }
00247 
00248     _init_ref_count--;
00249 
00250     if (_init_ref_count) {
00251         goto exit_point;
00252     }
00253 
00254     // Disable Device for Writing
00255     status = _spi_send_general_command(SPIF_WRDI, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
00256     if (status != SPIF_BD_ERROR_OK)  {
00257         tr_error("Write Disable failed");
00258     }
00259     _is_initialized = false;
00260 
00261 exit_point:
00262     _mutex->unlock();
00263 
00264     return status;
00265 }
00266 
00267 int SPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
00268 {
00269     if (!_is_initialized) {
00270         return BD_ERROR_DEVICE_ERROR;
00271     }
00272 
00273     int status = SPIF_BD_ERROR_OK;
00274     tr_debug("Read - Inst: 0x%xh", _read_instruction);
00275     _mutex->lock();
00276 
00277     // Set Dummy Cycles for Specific Read Command Mode
00278     _dummy_and_mode_cycles = _read_dummy_and_mode_cycles;
00279 
00280     status = _spi_send_read_command(_read_instruction, static_cast<uint8_t *>(buffer), addr, size);
00281 
00282     // Set Dummy Cycles for all other command modes
00283     _dummy_and_mode_cycles = _write_dummy_and_mode_cycles;
00284 
00285     _mutex->unlock();
00286     return status;
00287 }
00288 
00289 int SPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
00290 {
00291     if (!_is_initialized) {
00292         return BD_ERROR_DEVICE_ERROR;
00293     }
00294 
00295     bool program_failed = false;
00296     int status = SPIF_BD_ERROR_OK;
00297     uint32_t offset = 0;
00298     uint32_t chunk = 0;
00299 
00300     tr_debug("program - Buff: 0x%" PRIx32 "h, addr: %llu, size: %llu", (uint32_t)buffer, addr, size);
00301 
00302     while (size > 0) {
00303 
00304         // Write on _page_size_bytes boundaries (Default 256 bytes a page)
00305         offset = addr % _page_size_bytes;
00306         chunk = (offset + size < _page_size_bytes) ? size : (_page_size_bytes - offset);
00307 
00308         _mutex->lock();
00309 
00310         //Send WREN
00311         if (_set_write_enable() != 0) {
00312             tr_error("Write Enabe failed");
00313             program_failed = true;
00314             status = SPIF_BD_ERROR_WREN_FAILED;
00315             goto exit_point;
00316         }
00317 
00318         _spi_send_program_command(_prog_instruction, buffer, addr, chunk);
00319 
00320         buffer = static_cast<const uint8_t *>(buffer) + chunk;
00321         addr += chunk;
00322         size -= chunk;
00323 
00324         if (false == _is_mem_ready()) {
00325             tr_error("Device not ready after write, failed");
00326             program_failed = true;
00327             status = SPIF_BD_ERROR_READY_FAILED;
00328             goto exit_point;
00329         }
00330         _mutex->unlock();
00331     }
00332 
00333 exit_point:
00334     if (program_failed) {
00335         _mutex->unlock();
00336     }
00337 
00338     return status;
00339 }
00340 
00341 int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
00342 {
00343     if (!_is_initialized) {
00344         return BD_ERROR_DEVICE_ERROR;
00345     }
00346 
00347     int type = 0;
00348     uint32_t offset = 0;
00349     uint32_t chunk = 4096;
00350     int cur_erase_inst = _erase_instruction;
00351     int size = (int)in_size;
00352     bool erase_failed = false;
00353     int status = SPIF_BD_ERROR_OK;
00354     // Find region of erased address
00355     int region = _utils_find_addr_region(addr);
00356     if (region < 0) {
00357         tr_error("no region found for address %llu", addr);
00358         return SPIF_BD_ERROR_INVALID_ERASE_PARAMS;
00359     }
00360     // Erase Types of selected region
00361     uint8_t bitfield = _region_erase_types_bitfield[region];
00362 
00363     tr_debug("erase - addr: %llu, in_size: %llu", addr, in_size);
00364 
00365     if ((addr + in_size) > _device_size_bytes) {
00366         tr_error("erase exceeds flash device size");
00367         return SPIF_BD_ERROR_INVALID_ERASE_PARAMS;
00368     }
00369 
00370     if (((addr % get_erase_size(addr)) != 0) || (((addr + in_size) % get_erase_size(addr + in_size - 1)) != 0)) {
00371         tr_error("invalid erase - unaligned address and size");
00372         return SPIF_BD_ERROR_INVALID_ERASE_PARAMS;
00373     }
00374 
00375     // For each iteration erase the largest section supported by current region
00376     while (size > 0) {
00377 
00378         // iterate to find next Largest erase type ( a. supported by region, b. smaller than size)
00379         // find the matching instruction and erase size chunk for that type.
00380         type = _utils_iterate_next_largest_erase_type(bitfield, size, (unsigned int)addr, _region_high_boundary[region]);
00381         cur_erase_inst = _erase_type_inst_arr[type];
00382         offset = addr % _erase_type_size_arr[type];
00383         chunk = ((offset + size) < _erase_type_size_arr[type]) ? size : (_erase_type_size_arr[type] - offset);
00384 
00385         tr_debug("erase - addr: %llu, size:%d, Inst: 0x%xh, chunk: %" PRIu32 " , ",
00386                  addr, size, cur_erase_inst, chunk);
00387         tr_debug("erase - Region: %d, Type:%d",
00388                  region, type);
00389 
00390         _mutex->lock();
00391 
00392         if (_set_write_enable() != 0) {
00393             tr_error("SPI Erase Device not ready - failed");
00394             erase_failed = true;
00395             status = SPIF_BD_ERROR_READY_FAILED;
00396             goto exit_point;
00397         }
00398 
00399         _spi_send_erase_command(cur_erase_inst, addr, size);
00400 
00401         addr += chunk;
00402         size -= chunk;
00403 
00404         if ((size > 0) && (addr > _region_high_boundary[region])) {
00405             // erase crossed to next region
00406             region++;
00407             bitfield = _region_erase_types_bitfield[region];
00408         }
00409 
00410         if (false == _is_mem_ready()) {
00411             tr_error("SPI After Erase Device not ready - failed");
00412             erase_failed = true;
00413             status = SPIF_BD_ERROR_READY_FAILED;
00414             goto exit_point;
00415         }
00416 
00417         _mutex->unlock();
00418     }
00419 
00420 exit_point:
00421     if (erase_failed) {
00422         _mutex->unlock();
00423     }
00424 
00425     return status;
00426 }
00427 
00428 bd_size_t SPIFBlockDevice::get_read_size() const
00429 {
00430     // Assuming all devices support 1byte read granularity
00431     return SPIF_DEFAULT_READ_SIZE;
00432 }
00433 
00434 bd_size_t SPIFBlockDevice::get_program_size() const
00435 {
00436     // Assuming all devices support 1byte program granularity
00437     return SPIF_DEFAULT_PROG_SIZE;
00438 }
00439 
00440 bd_size_t SPIFBlockDevice::get_erase_size() const
00441 {
00442     // return minimal erase size supported by all regions (0 if none exists)
00443     return _min_common_erase_size;
00444 }
00445 
00446 // Find minimal erase size supported by the region to which the address belongs to
00447 bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr) const
00448 {
00449     // Find region of current address
00450     int region = _utils_find_addr_region(addr);
00451 
00452     unsigned int min_region_erase_size = _min_common_erase_size;
00453     int8_t type_mask = ERASE_BITMASK_TYPE1;
00454     int i_ind = 0;
00455 
00456     if (region != -1) {
00457         type_mask = 0x01;
00458 
00459         for (i_ind = 0; i_ind < 4; i_ind++) {
00460             // loop through erase types bitfield supported by region
00461             if (_region_erase_types_bitfield[region] & type_mask) {
00462 
00463                 min_region_erase_size = _erase_type_size_arr[i_ind];
00464                 break;
00465             }
00466             type_mask = type_mask << 1;
00467         }
00468 
00469         if (i_ind == 4) {
00470             tr_error("no erase type was found for region addr");
00471         }
00472     }
00473 
00474     return (bd_size_t)min_region_erase_size;
00475 }
00476 
00477 bd_size_t SPIFBlockDevice::size() const
00478 {
00479     if (!_is_initialized) {
00480         return 0;
00481     }
00482 
00483     return _device_size_bytes;
00484 }
00485 
00486 int SPIFBlockDevice::get_erase_value() const
00487 {
00488     return 0xFF;
00489 }
00490 
00491 const char *SPIFBlockDevice::get_type() const
00492 {
00493     return "SPIF";
00494 }
00495 
00496 /***************************************************/
00497 /*********** SPI Driver API Functions **************/
00498 /***************************************************/
00499 spif_bd_error SPIFBlockDevice::_spi_set_frequency(int freq)
00500 {
00501     _spi.frequency(freq);
00502     return SPIF_BD_ERROR_OK;
00503 }
00504 
00505 spif_bd_error SPIFBlockDevice::_spi_send_read_command(int read_inst, uint8_t *buffer, bd_addr_t addr, bd_size_t size)
00506 {
00507     uint32_t dummy_bytes = _dummy_and_mode_cycles / 8;
00508     int dummy_byte = 0;
00509 
00510     // csel must go low for the entire command (Inst, Address and Data)
00511     _cs = 0;
00512 
00513     // Write 1 byte Instruction
00514     _spi.write(read_inst);
00515 
00516     // Write Address (can be either 3 or 4 bytes long)
00517     for (int address_shift = ((_address_size - 1) * 8); address_shift >= 0; address_shift -= 8) {
00518         _spi.write((addr >> address_shift) & 0xFF);
00519     }
00520 
00521     // Write Dummy Cycles Bytes
00522     for (uint32_t i = 0; i < dummy_bytes; i++) {
00523         _spi.write(dummy_byte);
00524     }
00525 
00526     // Read Data
00527     for (bd_size_t i = 0; i < size; i++) {
00528         buffer[i] = _spi.write(0);
00529     }
00530 
00531     // csel back to high
00532     _cs = 1;
00533     return SPIF_BD_ERROR_OK;
00534 }
00535 
00536 spif_bd_error SPIFBlockDevice::_spi_send_program_command(int prog_inst, const void *buffer, bd_addr_t addr,
00537                                                          bd_size_t size)
00538 {
00539     // Send Program (write) command to device driver
00540     uint32_t dummy_bytes = _dummy_and_mode_cycles / 8;
00541     int dummy_byte = 0;
00542     uint8_t *data = (uint8_t *)buffer;
00543 
00544     // csel must go low for the entire command (Inst, Address and Data)
00545     _cs = 0;
00546 
00547     // Write 1 byte Instruction
00548     _spi.write(prog_inst);
00549 
00550     // Write Address (can be either 3 or 4 bytes long)
00551     for (int address_shift = ((_address_size - 1) * 8); address_shift >= 0; address_shift -= 8) {
00552         _spi.write((addr >> address_shift) & 0xFF);
00553     }
00554 
00555     // Write Dummy Cycles Bytes
00556     for (uint32_t i = 0; i < dummy_bytes; i++) {
00557         _spi.write(dummy_byte);
00558     }
00559 
00560     // Write Data
00561     for (bd_size_t i = 0; i < size; i++) {
00562         _spi.write(data[i]);
00563     }
00564 
00565     // csel back to high
00566     _cs = 1;
00567 
00568     return SPIF_BD_ERROR_OK;
00569 }
00570 
00571 spif_bd_error SPIFBlockDevice::_spi_send_erase_command(int erase_inst, bd_addr_t addr, bd_size_t size)
00572 {
00573     tr_debug("Erase Inst: 0x%xh, addr: %llu, size: %llu", erase_inst, addr, size);
00574     addr = (((int)addr) & 0xFFFFF000);
00575     _spi_send_general_command(erase_inst, addr, NULL, 0, NULL, 0);
00576     return SPIF_BD_ERROR_OK;
00577 }
00578 
00579 spif_bd_error SPIFBlockDevice::_spi_send_general_command(int instruction, bd_addr_t addr, char *tx_buffer,
00580                                                          size_t tx_length, char *rx_buffer, size_t rx_length)
00581 {
00582     // Send a general command Instruction to driver
00583     uint32_t dummy_bytes = _dummy_and_mode_cycles / 8;
00584     uint8_t dummy_byte = 0x00;
00585 
00586     // csel must go low for the entire command (Inst, Address and Data)
00587     _cs = 0;
00588 
00589     // Write 1 byte Instruction
00590     _spi.write(instruction);
00591 
00592     // Reading SPI Bus registers does not require Flash Address
00593     if (addr != SPI_NO_ADDRESS_COMMAND) {
00594         // Write Address (can be either 3 or 4 bytes long)
00595         for (int address_shift = ((_address_size - 1) * 8); address_shift >= 0; address_shift -= 8) {
00596             _spi.write((addr >> address_shift) & 0xFF);
00597         }
00598 
00599         // Write Dummy Cycles Bytes
00600         for (uint32_t i = 0; i < dummy_bytes; i++) {
00601             _spi.write(dummy_byte);
00602         }
00603     }
00604 
00605     // Read/Write Data
00606     _spi.write(tx_buffer, (int)tx_length, rx_buffer, (int)rx_length);
00607 
00608     // csel back to high
00609     _cs = 1;
00610 
00611     return SPIF_BD_ERROR_OK;
00612 }
00613 
00614 /*********************************************************/
00615 /********** SFDP Parsing and Detection Functions *********/
00616 /*********************************************************/
00617 int SPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size)
00618 {
00619     uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
00620     uint32_t tmp_region_size = 0;
00621     int i_ind = 0;
00622     int prev_boundary = 0;
00623     // Default set to all type bits 1-4 are common
00624     int min_common_erase_type_bits = ERASE_BITMASK_ALL;
00625 
00626 
00627     spif_bd_error status = _spi_send_read_command(SPIF_SFDP, sector_map_table, sector_map_table_addr /*address*/,
00628                                                   sector_map_table_size);
00629     if (status != SPIF_BD_ERROR_OK) {
00630         tr_error("init - Read SFDP First Table Failed");
00631         return -1;
00632     }
00633 
00634     // Currently we support only Single Map Descriptor
00635     if (!((sector_map_table[0] & 0x3) == 0x03) && (sector_map_table[1]  == 0x0)) {
00636         tr_error("Sector Map - Supporting Only Single! Map Descriptor (not map commands)");
00637         return -1;
00638     }
00639 
00640     _regions_count = sector_map_table[2] + 1;
00641     if (_regions_count > SPIF_MAX_REGIONS) {
00642         tr_error("Supporting up to %d regions, current setup to %d regions - fail",
00643                  SPIF_MAX_REGIONS, _regions_count);
00644         return -1;
00645     }
00646 
00647     // Loop through Regions and set for each one: size, supported erase types, high boundary offset
00648     // Calculate minimum Common Erase Type for all Regions
00649     for (i_ind = 0; i_ind < _regions_count; i_ind++) {
00650         tmp_region_size = ((*((uint32_t *)&sector_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32
00651         _region_size_bytes[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes;
00652         _region_erase_types_bitfield[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4
00653         min_common_erase_type_bits &= _region_erase_types_bitfield[i_ind];
00654         _region_high_boundary[i_ind] = (_region_size_bytes[i_ind] - 1) + prev_boundary;
00655         prev_boundary = _region_high_boundary[i_ind] + 1;
00656     }
00657 
00658     // Calc minimum Common Erase Size from min_common_erase_type_bits
00659     uint8_t type_mask = ERASE_BITMASK_TYPE1;
00660     for (i_ind = 0; i_ind < 4; i_ind++) {
00661         if (min_common_erase_type_bits & type_mask) {
00662             _min_common_erase_size = _erase_type_size_arr[i_ind];
00663             break;
00664         }
00665         type_mask = type_mask << 1;
00666     }
00667 
00668     if (i_ind == 4) {
00669         // No common erase type was found between regions
00670         _min_common_erase_size = 0;
00671     }
00672 
00673     return 0;
00674 }
00675 
00676 int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size)
00677 {
00678     uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
00679     //memset(param_table, 0, SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES);
00680 
00681     spif_bd_error status = _spi_send_read_command(SPIF_SFDP, param_table, basic_table_addr /*address*/,
00682                                                   basic_table_size);
00683     if (status != SPIF_BD_ERROR_OK) {
00684         tr_error("init - Read SFDP First Table Failed");
00685         return -1;
00686     }
00687 
00688     // Check address size, currently only supports 3byte addresses
00689     if ((param_table[2] & 0x4) != 0 || (param_table[7] & 0x80) != 0) {
00690         tr_error("init - verify 3byte addressing Failed");
00691         return -1;
00692     }
00693 
00694     // Get device density (stored in bits - 1)
00695     uint32_t density_bits = (
00696                                 (param_table[7] << 24) |
00697                                 (param_table[6] << 16) |
00698                                 (param_table[5] << 8) |
00699                                 param_table[4]);
00700     _device_size_bytes = (density_bits + 1) / 8;
00701     tr_debug("Density bits: %" PRIu32 " , device size: %llu bytes", density_bits, _device_size_bytes);
00702 
00703     // Set Default read/program/erase Instructions
00704     _read_instruction = SPIF_READ;
00705     _prog_instruction = SPIF_PP;
00706     _erase_instruction = SPIF_SE;
00707 
00708     // Set Page Size (SPI write must be done on Page limits)
00709     _page_size_bytes = _sfdp_detect_page_size(param_table, basic_table_size);
00710 
00711     // Detect and Set Erase Types
00712     _sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _erase4k_inst, _erase_type_inst_arr,
00713                                            _erase_type_size_arr);
00714     _erase_instruction = _erase4k_inst;
00715 
00716     // Detect and Set fastest Bus mode (default 1-1-1)
00717     _sfdp_detect_best_bus_read_mode(param_table, basic_table_size, _read_instruction);
00718 
00719     return 0;
00720 }
00721 
00722 int SPIFBlockDevice::_sfdp_parse_sfdp_headers(uint32_t &basic_table_addr, size_t &basic_table_size,
00723                                               uint32_t &sector_map_table_addr, size_t &sector_map_table_size)
00724 {
00725     uint8_t sfdp_header[16];
00726     uint8_t param_header[SPIF_SFDP_HEADER_SIZE];
00727     size_t data_length = SPIF_SFDP_HEADER_SIZE;
00728     bd_addr_t addr = 0x0;
00729 
00730     // Set 1-1-1 bus mode for SFDP header parsing
00731     // Initial SFDP read tables are read with 8 dummy cycles
00732     _read_dummy_and_mode_cycles = 8;
00733     _dummy_and_mode_cycles = 8;
00734 
00735     spif_bd_error status = _spi_send_read_command(SPIF_SFDP, sfdp_header, addr /*address*/, data_length);
00736     if (status != SPIF_BD_ERROR_OK) {
00737         tr_error("init - Read SFDP Failed");
00738         return -1;
00739     }
00740 
00741     // Verify SFDP signature for sanity
00742     // Also check that major/minor version is acceptable
00743     if (!(memcmp(&sfdp_header[0], "SFDP", 4) == 0 && sfdp_header[5] == 1)) {
00744         tr_error("init - _verify SFDP signature and version Failed");
00745         return -1;
00746     } else {
00747         tr_debug("init - verified SFDP Signature and version Successfully");
00748     }
00749 
00750     // Discover Number of Parameter Headers
00751     int number_of_param_headers = (int)(sfdp_header[6]) + 1;
00752     tr_debug("number of Param Headers: %d", number_of_param_headers);
00753 
00754     addr += SPIF_SFDP_HEADER_SIZE;
00755     data_length = SPIF_PARAM_HEADER_SIZE;
00756 
00757     // Loop over Param Headers and parse them (currently supported Basic Param Table and Sector Region Map Table)
00758     for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) {
00759 
00760         status = _spi_send_read_command(SPIF_SFDP, param_header, addr, data_length);
00761         if (status != SPIF_BD_ERROR_OK) {
00762             tr_error("init - Read Param Table %d Failed", i_ind + 1);
00763             return -1;
00764         }
00765 
00766         // The SFDP spec indicates the standard table is always at offset 0
00767         // in the parameter headers, we check just to be safe
00768         if (param_header[2] != 1) {
00769             tr_error("Param Table %d - Major Version should be 1!", i_ind + 1);
00770             return -1;
00771         }
00772 
00773         if ((param_header[0] == 0) && (param_header[7] == 0xFF)) {
00774             // Found Basic Params Table: LSB=0x00, MSB=0xFF
00775             tr_debug("Found Basic Param Table at Table: %d", i_ind + 1);
00776             basic_table_addr = ((param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]));
00777             // Supporting up to 64 Bytes Table (16 DWORDS)
00778             basic_table_size = ((param_header[3] * 4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[3] * 4) : 64;
00779 
00780         } else if ((param_header[0] == 81) && (param_header[7] == 0xFF)) {
00781             // Found Sector Map Table: LSB=0x81, MSB=0xFF
00782             tr_debug("Found Sector Map Table at Table: %d", i_ind + 1);
00783             sector_map_table_addr = ((param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]));
00784             sector_map_table_size = param_header[3] * 4;
00785 
00786         }
00787         addr += SPIF_PARAM_HEADER_SIZE;
00788 
00789     }
00790     return 0;
00791 }
00792 
00793 unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size)
00794 {
00795     unsigned int page_size = SPIF_DEFAULT_PAGE_SIZE;
00796 
00797     if (basic_param_table_size > SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE) {
00798         // Page Size is specified by 4 Bits (N), calculated by 2^N
00799         int page_to_power_size = ((int)basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4;
00800         page_size = local_math_power(2, page_to_power_size);
00801         tr_debug("Detected Page Size: %d", page_size);
00802     } else {
00803         tr_debug("Using Default Page Size: %d", page_size);
00804     }
00805     return page_size;
00806 }
00807 
00808 int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size,
00809                                                             int &erase4k_inst,
00810                                                             int *erase_type_inst_arr, unsigned int *erase_type_size_arr)
00811 {
00812     erase4k_inst = 0xff;
00813     bool found_4Kerase_type = false;
00814     uint8_t bitfield = 0x01;
00815 
00816     // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
00817     erase4k_inst = basic_param_table_ptr[SPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
00818 
00819     if (basic_param_table_size > SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE) {
00820         // Loop Erase Types 1-4
00821         for (int i_ind = 0; i_ind < 4; i_ind++) {
00822             erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type
00823             erase_type_size_arr[i_ind] = local_math_power(2,
00824                                                           basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N
00825             tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), erase_type_inst_arr[i_ind],
00826                      erase_type_size_arr[i_ind]);
00827             if (erase_type_size_arr[i_ind] > 1) {
00828                 // if size==1 type is not supported
00829                 erase_type_inst_arr[i_ind] = basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind];
00830 
00831                 if ((erase_type_size_arr[i_ind] < _min_common_erase_size) || (_min_common_erase_size == 0)) {
00832                     //Set default minimal common erase for singal region
00833                     _min_common_erase_size = erase_type_size_arr[i_ind];
00834                 }
00835 
00836                 // SFDP standard requires 4K Erase type to exist and its instruction to be identical to legacy field erase instruction
00837                 if (erase_type_size_arr[i_ind] == 4096) {
00838                     found_4Kerase_type = true;
00839                     if (erase4k_inst != erase_type_inst_arr[i_ind]) {
00840                         //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table
00841                         erase4k_inst = erase_type_inst_arr[i_ind];
00842                         tr_warning("_detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K");
00843 
00844                     }
00845                 }
00846                 _region_erase_types_bitfield[0] |= bitfield; // If there's no region map, set region "0" types bitfield as defualt;
00847             }
00848             tr_info("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1),
00849                     erase_type_inst_arr[i_ind], erase_type_size_arr[i_ind]);
00850             bitfield = bitfield << 1;
00851         }
00852     }
00853 
00854     if (false == found_4Kerase_type) {
00855         tr_warning("Couldn't find Erase Type for 4KB size");
00856     }
00857     return 0;
00858 }
00859 
00860 int SPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size,
00861                                                      int &read_inst)
00862 {
00863     do {
00864 
00865         // TBD - SPIF Dual Read Modes Require SPI driver support
00866         _read_dummy_and_mode_cycles = 0;
00867         tr_debug("Read Bus Mode set to 1-1-1, Instruction: 0x%xh", read_inst);
00868     } while (false);
00869 
00870     return 0;
00871 }
00872 
00873 int SPIFBlockDevice::_reset_flash_mem()
00874 {
00875     // Perform Soft Reset of the Device prior to initialization
00876     int status = 0;
00877     char status_value[2] = {0};
00878     tr_info("_reset_flash_mem:");
00879     //Read the Status Register from device
00880     if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value, 1)) {
00881         // store received values in status_value
00882         tr_debug("Reading Status Register Success: value = 0x%x", (int)status_value[0]);
00883     } else {
00884         tr_error("Reading Status Register failed");
00885         status = -1;
00886     }
00887 
00888     if (0 == status) {
00889         //Send Reset Enable
00890         if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RSTEN, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0)) {
00891             // store received values in status_value
00892             tr_debug("Sending RSTEN Success");
00893         } else {
00894             tr_error("Sending RSTEN failed");
00895             status = -1;
00896         }
00897 
00898         if (0 == status) {
00899             //Send Reset
00900             if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RST, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0)) {
00901                 // store received values in status_value
00902                 tr_debug("Sending RST Success");
00903             } else {
00904                 tr_error("Sending RST failed");
00905                 status = -1;
00906             }
00907             if (false == _is_mem_ready()) {
00908                 tr_error("Device not ready, write failed");
00909                 status = -1;
00910             }
00911         }
00912     }
00913 
00914     return status;
00915 }
00916 
00917 bool SPIFBlockDevice::_is_mem_ready()
00918 {
00919     // Check Status Register Busy Bit to Verify the Device isn't Busy
00920     char status_value[2];
00921     int retries = 0;
00922     bool mem_ready = true;
00923 
00924     do {
00925         rtos::ThisThread::sleep_for(1);
00926         retries++;
00927         //Read the Status Register from device
00928         if (SPIF_BD_ERROR_OK != _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value,
00929                                                           1)) {   // store received values in status_value
00930             tr_error("Reading Status Register failed");
00931         }
00932     } while ((status_value[0] & SPIF_STATUS_BIT_WIP) != 0 && retries < IS_MEM_READY_MAX_RETRIES);
00933 
00934     if ((status_value[0] & SPIF_STATUS_BIT_WIP) != 0) {
00935         tr_error("_is_mem_ready FALSE");
00936         mem_ready = false;
00937     }
00938     return mem_ready;
00939 }
00940 
00941 int SPIFBlockDevice::_set_write_enable()
00942 {
00943     // Check Status Register Busy Bit to Verify the Device isn't Busy
00944     char status_value[2];
00945     int status = -1;
00946 
00947     do {
00948         if (SPIF_BD_ERROR_OK !=  _spi_send_general_command(SPIF_WREN, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0)) {
00949             tr_error("Sending WREN command FAILED");
00950             break;
00951         }
00952 
00953         if (false == _is_mem_ready()) {
00954             tr_error("Device not ready, write failed");
00955             break;
00956         }
00957 
00958         memset(status_value, 0, 2);
00959         if (SPIF_BD_ERROR_OK != _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value,
00960                                                           1)) {   // store received values in status_value
00961             tr_error("Reading Status Register failed");
00962             break;
00963         }
00964 
00965         if ((status_value[0] & SPIF_STATUS_BIT_WEL) == 0) {
00966             tr_error("_set_write_enable failed");
00967             break;
00968         }
00969         status = 0;
00970     } while (false);
00971     return status;
00972 }
00973 
00974 /*********************************************/
00975 /************* Utility Functions *************/
00976 /*********************************************/
00977 int SPIFBlockDevice::_utils_find_addr_region(bd_size_t offset) const
00978 {
00979     //Find the region to which the given offset belong to
00980     if ((offset > _device_size_bytes) || (_regions_count == 0)) {
00981         return -1;
00982     }
00983 
00984     if (_regions_count == 1) {
00985         return 0;
00986     }
00987 
00988     for (int i_ind = _regions_count - 2; i_ind >= 0; i_ind--) {
00989 
00990         if (offset > _region_high_boundary[i_ind]) {
00991             return (i_ind + 1);
00992         }
00993     }
00994     return -1;
00995 
00996 }
00997 
00998 int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry)
00999 {
01000     // Iterate on all supported Erase Types of the Region to which the offset belong to.
01001     // Iterates from highest type to lowest
01002     uint8_t type_mask = ERASE_BITMASK_TYPE4;
01003     int i_ind  = 0;
01004     int largest_erase_type = 0;
01005     for (i_ind = 3; i_ind >= 0; i_ind--) {
01006         if (bitfield & type_mask) {
01007             largest_erase_type = i_ind;
01008             if ((size > (int)(_erase_type_size_arr[largest_erase_type])) &&
01009                     ((boundry - offset) > (int)(_erase_type_size_arr[largest_erase_type]))) {
01010                 break;
01011             } else {
01012                 bitfield &= ~type_mask;
01013             }
01014         }
01015         type_mask = type_mask >> 1;
01016     }
01017 
01018     if (i_ind == 4) {
01019         tr_error("no erase type was found for current region addr");
01020     }
01021     return largest_erase_type;
01022 
01023 }
01024 
01025 /*********************************************/
01026 /************** Local Functions **************/
01027 /*********************************************/
01028 static unsigned int local_math_power(int base, int exp)
01029 {
01030     // Integer X^Y function, used to calculate size fields given in 2^N format
01031     int result = 1;
01032     while (exp) {
01033         result *= base;
01034         exp--;
01035     }
01036     return result;
01037 }
01038 
01039