Jim Carver
/
mbed-cloud-workshop-connect-HTS221
bug fix
qspi-blockdevice/QSPIFBlockDevice.cpp@0:6b753f761943, 2018-10-12 (annotated)
- Committer:
- JimCarver
- Date:
- Fri Oct 12 21:22:49 2018 +0000
- Revision:
- 0:6b753f761943
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
JimCarver | 0:6b753f761943 | 1 | |
JimCarver | 0:6b753f761943 | 2 | /* mbed Microcontroller Library |
JimCarver | 0:6b753f761943 | 3 | * Copyright (c) 2016 ARM Limited |
JimCarver | 0:6b753f761943 | 4 | * |
JimCarver | 0:6b753f761943 | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
JimCarver | 0:6b753f761943 | 6 | * you may not use this file except in compliance with the License. |
JimCarver | 0:6b753f761943 | 7 | * You may obtain a copy of the License at |
JimCarver | 0:6b753f761943 | 8 | * |
JimCarver | 0:6b753f761943 | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
JimCarver | 0:6b753f761943 | 10 | * |
JimCarver | 0:6b753f761943 | 11 | * Unless required by applicable law or agreed to in writing, software |
JimCarver | 0:6b753f761943 | 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
JimCarver | 0:6b753f761943 | 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
JimCarver | 0:6b753f761943 | 14 | * See the License for the specific language governing permissions and |
JimCarver | 0:6b753f761943 | 15 | * limitations under the License. |
JimCarver | 0:6b753f761943 | 16 | */ |
JimCarver | 0:6b753f761943 | 17 | |
JimCarver | 0:6b753f761943 | 18 | //#include "./mbed-os/drivers/qspi.h" |
JimCarver | 0:6b753f761943 | 19 | |
JimCarver | 0:6b753f761943 | 20 | #define DEVICE_QSPI 1 |
JimCarver | 0:6b753f761943 | 21 | |
JimCarver | 0:6b753f761943 | 22 | #include "QSPIFBlockDevice.h" |
JimCarver | 0:6b753f761943 | 23 | |
JimCarver | 0:6b753f761943 | 24 | /* Default QSPIF Parameters */ |
JimCarver | 0:6b753f761943 | 25 | /****************************/ |
JimCarver | 0:6b753f761943 | 26 | #define QSPIF_DEFAULT_READ_SIZE 1 |
JimCarver | 0:6b753f761943 | 27 | #define QSPIF_DEFAULT_PROG_SIZE 1 |
JimCarver | 0:6b753f761943 | 28 | #define QSPIF_DEFAULT_SE_SIZE 4096 |
JimCarver | 0:6b753f761943 | 29 | #define QSPI_MAX_STATUS_REGISTER_SIZE 2 |
JimCarver | 0:6b753f761943 | 30 | #define QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC 50 |
JimCarver | 0:6b753f761943 | 31 | #define QSPIF_DEFAULT_TIMEOUT_MSEC 1 |
JimCarver | 0:6b753f761943 | 32 | |
JimCarver | 0:6b753f761943 | 33 | |
JimCarver | 0:6b753f761943 | 34 | /* SFDP Header Parsing */ |
JimCarver | 0:6b753f761943 | 35 | /***********************/ |
JimCarver | 0:6b753f761943 | 36 | #define QSPIF_SFDP_HEADER_SIZE 8 |
JimCarver | 0:6b753f761943 | 37 | #define QSPIF_PARAM_HEADER_SIZE 8 |
JimCarver | 0:6b753f761943 | 38 | |
JimCarver | 0:6b753f761943 | 39 | /* Basic Parameters Table Parsing */ |
JimCarver | 0:6b753f761943 | 40 | /**********************************/ |
JimCarver | 0:6b753f761943 | 41 | #define SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES 64 /* 16 DWORDS */ |
JimCarver | 0:6b753f761943 | 42 | //READ Instruction support according to BUS Configuration |
JimCarver | 0:6b753f761943 | 43 | #define QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE 2 |
JimCarver | 0:6b753f761943 | 44 | #define QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE 16 |
JimCarver | 0:6b753f761943 | 45 | #define QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE 27 |
JimCarver | 0:6b753f761943 | 46 | #define QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE 9 |
JimCarver | 0:6b753f761943 | 47 | #define QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE 11 |
JimCarver | 0:6b753f761943 | 48 | #define QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23 |
JimCarver | 0:6b753f761943 | 49 | #define QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15 |
JimCarver | 0:6b753f761943 | 50 | #define QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13 |
JimCarver | 0:6b753f761943 | 51 | #define QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE 40 |
JimCarver | 0:6b753f761943 | 52 | // Quad Enable Params |
JimCarver | 0:6b753f761943 | 53 | #define QSPIF_BASIC_PARAM_TABLE_QER_BYTE 58 |
JimCarver | 0:6b753f761943 | 54 | #define QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE 56 |
JimCarver | 0:6b753f761943 | 55 | // Erase Types Params |
JimCarver | 0:6b753f761943 | 56 | #define QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE 29 |
JimCarver | 0:6b753f761943 | 57 | #define QSPIF_BASIC_PARAM_ERASE_TYPE_2_BYTE 31 |
JimCarver | 0:6b753f761943 | 58 | #define QSPIF_BASIC_PARAM_ERASE_TYPE_3_BYTE 33 |
JimCarver | 0:6b753f761943 | 59 | #define QSPIF_BASIC_PARAM_ERASE_TYPE_4_BYTE 35 |
JimCarver | 0:6b753f761943 | 60 | #define QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE 28 |
JimCarver | 0:6b753f761943 | 61 | #define QSPIF_BASIC_PARAM_ERASE_TYPE_2_SIZE_BYTE 30 |
JimCarver | 0:6b753f761943 | 62 | #define QSPIF_BASIC_PARAM_ERASE_TYPE_3_SIZE_BYTE 32 |
JimCarver | 0:6b753f761943 | 63 | #define QSPIF_BASIC_PARAM_ERASE_TYPE_4_SIZE_BYTE 34 |
JimCarver | 0:6b753f761943 | 64 | #define QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1 |
JimCarver | 0:6b753f761943 | 65 | |
JimCarver | 0:6b753f761943 | 66 | // Debug Printouts |
JimCarver | 0:6b753f761943 | 67 | #define QSPIF_DEBUG_ERROR 1 |
JimCarver | 0:6b753f761943 | 68 | #define QSPIF_DEBUG_WARNING 2 |
JimCarver | 0:6b753f761943 | 69 | #define QSPIF_DEBUG_INFO 3 |
JimCarver | 0:6b753f761943 | 70 | #define QSPIF_DEBUG_DEBUG 4 |
JimCarver | 0:6b753f761943 | 71 | #define QSPIF_DEBUG_TRACE 5 |
JimCarver | 0:6b753f761943 | 72 | // #define QSPIF_DEFAULT_DEBUG_LEVEL QSPIF_DEBUG_INFO |
JimCarver | 0:6b753f761943 | 73 | // #define QSPIF_DEFAULT_DEBUG_LEVEL QSPIF_DEBUG_TRACE |
JimCarver | 0:6b753f761943 | 74 | #define QSPIF_DEFAULT_DEBUG_LEVEL QSPIF_DEBUG_WARNING |
JimCarver | 0:6b753f761943 | 75 | |
JimCarver | 0:6b753f761943 | 76 | |
JimCarver | 0:6b753f761943 | 77 | enum qspif_default_instructions { |
JimCarver | 0:6b753f761943 | 78 | QSPIF_NOP = 0x00, // No operation |
JimCarver | 0:6b753f761943 | 79 | QSPIF_PP = 0x02, // Page Program data |
JimCarver | 0:6b753f761943 | 80 | QSPIF_READ = 0x03, // Read data |
JimCarver | 0:6b753f761943 | 81 | QSPIF_SE = 0x20, // 4KB Sector Erase |
JimCarver | 0:6b753f761943 | 82 | QSPIF_SFDP = 0x5a, // Read SFDP |
JimCarver | 0:6b753f761943 | 83 | |
JimCarver | 0:6b753f761943 | 84 | QSPIF_WRSR = 0x01, // Write Status/Configuration Register |
JimCarver | 0:6b753f761943 | 85 | QSPIF_WRDI = 0x04, // Write Disable |
JimCarver | 0:6b753f761943 | 86 | QSPIF_RDSR = 0x05, // Read Status Register |
JimCarver | 0:6b753f761943 | 87 | QSPIF_WREN = 0x06, // Write Enable |
JimCarver | 0:6b753f761943 | 88 | |
JimCarver | 0:6b753f761943 | 89 | QSPIF_RSTEN = 0x66, // Reset Enable |
JimCarver | 0:6b753f761943 | 90 | QSPIF_RST = 0x99, // Reset |
JimCarver | 0:6b753f761943 | 91 | QSPIF_RDID = 0x9f, // Read Manufacturer and JDEC Device ID |
JimCarver | 0:6b753f761943 | 92 | }; |
JimCarver | 0:6b753f761943 | 93 | |
JimCarver | 0:6b753f761943 | 94 | #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) |
JimCarver | 0:6b753f761943 | 95 | |
JimCarver | 0:6b753f761943 | 96 | #define QSPIF_LOG(level,...) {\ |
JimCarver | 0:6b753f761943 | 97 | if (level <= QSPIF_DEFAULT_DEBUG_LEVEL) {\ |
JimCarver | 0:6b753f761943 | 98 | char str[256];\ |
JimCarver | 0:6b753f761943 | 99 | sprintf(str, "\n[%s][%s:%d], ", __FILENAME__, __FUNCTION__, __LINE__);\ |
JimCarver | 0:6b753f761943 | 100 | sprintf(str+strlen(str),__VA_ARGS__);\ |
JimCarver | 0:6b753f761943 | 101 | printf(str);\ |
JimCarver | 0:6b753f761943 | 102 | }\ |
JimCarver | 0:6b753f761943 | 103 | } |
JimCarver | 0:6b753f761943 | 104 | |
JimCarver | 0:6b753f761943 | 105 | // Mutex is used for some QSPI Driver commands that must be done sequentially with no other commands in between |
JimCarver | 0:6b753f761943 | 106 | // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready |
JimCarver | 0:6b753f761943 | 107 | SingletonPtr<PlatformMutex> QSPIFBlockDevice::_mutex; |
JimCarver | 0:6b753f761943 | 108 | |
JimCarver | 0:6b753f761943 | 109 | |
JimCarver | 0:6b753f761943 | 110 | /********* Public API Functions *********/ |
JimCarver | 0:6b753f761943 | 111 | /****************************************/ |
JimCarver | 0:6b753f761943 | 112 | |
JimCarver | 0:6b753f761943 | 113 | QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel, |
JimCarver | 0:6b753f761943 | 114 | int clock_mode, int freq) |
JimCarver | 0:6b753f761943 | 115 | : _qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _deviceSizeBytes(0) |
JimCarver | 0:6b753f761943 | 116 | { |
JimCarver | 0:6b753f761943 | 117 | //_cs = 1; |
JimCarver | 0:6b753f761943 | 118 | is_initialized = false; |
JimCarver | 0:6b753f761943 | 119 | _minCommonEraseSize = 0; |
JimCarver | 0:6b753f761943 | 120 | _regions_count = 1; |
JimCarver | 0:6b753f761943 | 121 | _region_erase_types[0] = 0; |
JimCarver | 0:6b753f761943 | 122 | |
JimCarver | 0:6b753f761943 | 123 | //Default Bus Setup 1_1_1 with 0 dummy and mode cycles |
JimCarver | 0:6b753f761943 | 124 | _inst_width = QSPI_CFG_BUS_SINGLE; |
JimCarver | 0:6b753f761943 | 125 | _address_width = QSPI_CFG_BUS_SINGLE; |
JimCarver | 0:6b753f761943 | 126 | _address_size = QSPI_CFG_ADDR_SIZE_24; |
JimCarver | 0:6b753f761943 | 127 | _alt_width = QSPI_CFG_BUS_SINGLE; |
JimCarver | 0:6b753f761943 | 128 | _alt_size = QSPI_CFG_ALT_SIZE_8; |
JimCarver | 0:6b753f761943 | 129 | _data_width = QSPI_CFG_BUS_SINGLE; |
JimCarver | 0:6b753f761943 | 130 | _dummy_and_mode_cycles = 0; |
JimCarver | 0:6b753f761943 | 131 | |
JimCarver | 0:6b753f761943 | 132 | if (QSPI_STATUS_OK != _qspiSetFrequency(freq)) { |
JimCarver | 0:6b753f761943 | 133 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Set Frequency Failed"); |
JimCarver | 0:6b753f761943 | 134 | } |
JimCarver | 0:6b753f761943 | 135 | } |
JimCarver | 0:6b753f761943 | 136 | |
JimCarver | 0:6b753f761943 | 137 | |
JimCarver | 0:6b753f761943 | 138 | int QSPIFBlockDevice::init() |
JimCarver | 0:6b753f761943 | 139 | { |
JimCarver | 0:6b753f761943 | 140 | |
JimCarver | 0:6b753f761943 | 141 | uint8_t vendor_device_ids[4]; |
JimCarver | 0:6b753f761943 | 142 | size_t data_length = 3; |
JimCarver | 0:6b753f761943 | 143 | |
JimCarver | 0:6b753f761943 | 144 | _mutex->lock(); |
JimCarver | 0:6b753f761943 | 145 | if (is_initialized == true) { |
JimCarver | 0:6b753f761943 | 146 | _mutex->unlock(); |
JimCarver | 0:6b753f761943 | 147 | return 0; |
JimCarver | 0:6b753f761943 | 148 | } |
JimCarver | 0:6b753f761943 | 149 | |
JimCarver | 0:6b753f761943 | 150 | // Soft Reset |
JimCarver | 0:6b753f761943 | 151 | if ( -1 == _resetFlashMem()) { |
JimCarver | 0:6b753f761943 | 152 | QSPIF_LOG(QSPIF_DEBUG_INFO, "ERROR: init - Unable to initialize flash memory, tests failed\n"); |
JimCarver | 0:6b753f761943 | 153 | return -1; |
JimCarver | 0:6b753f761943 | 154 | } else { |
JimCarver | 0:6b753f761943 | 155 | QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: Initialize flash memory OK\n"); |
JimCarver | 0:6b753f761943 | 156 | } |
JimCarver | 0:6b753f761943 | 157 | |
JimCarver | 0:6b753f761943 | 158 | |
JimCarver | 0:6b753f761943 | 159 | |
JimCarver | 0:6b753f761943 | 160 | /* Read Manufacturer ID (1byte), and Device ID (2bytes)*/ |
JimCarver | 0:6b753f761943 | 161 | int status = _qspiSendReadCommand(QSPIF_RDID, (char *)vendor_device_ids, 0x0 /*address*/, data_length); |
JimCarver | 0:6b753f761943 | 162 | if (status != QSPI_STATUS_OK) { |
JimCarver | 0:6b753f761943 | 163 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read Vendor ID Failed"); |
JimCarver | 0:6b753f761943 | 164 | return status; |
JimCarver | 0:6b753f761943 | 165 | } |
JimCarver | 0:6b753f761943 | 166 | |
JimCarver | 0:6b753f761943 | 167 | switch (vendor_device_ids[0]) { |
JimCarver | 0:6b753f761943 | 168 | case 0xbf: |
JimCarver | 0:6b753f761943 | 169 | // SST devices come preset with block protection |
JimCarver | 0:6b753f761943 | 170 | // enabled for some regions, issue write disable instruction to clear |
JimCarver | 0:6b753f761943 | 171 | _setWriteEnable(); |
JimCarver | 0:6b753f761943 | 172 | //_cmdwrite(0x98, 0, 0, 0x0, NULL); |
JimCarver | 0:6b753f761943 | 173 | _qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0); |
JimCarver | 0:6b753f761943 | 174 | |
JimCarver | 0:6b753f761943 | 175 | break; |
JimCarver | 0:6b753f761943 | 176 | } |
JimCarver | 0:6b753f761943 | 177 | |
JimCarver | 0:6b753f761943 | 178 | //Synchronize Device |
JimCarver | 0:6b753f761943 | 179 | if ( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 180 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - _isMemReady Failed"); |
JimCarver | 0:6b753f761943 | 181 | return BD_ERROR_DEVICE_ERROR; |
JimCarver | 0:6b753f761943 | 182 | } |
JimCarver | 0:6b753f761943 | 183 | |
JimCarver | 0:6b753f761943 | 184 | |
JimCarver | 0:6b753f761943 | 185 | /**************************** Parse SFDP Header ***********************************/ |
JimCarver | 0:6b753f761943 | 186 | uint32_t basic_table_addr = NULL; |
JimCarver | 0:6b753f761943 | 187 | size_t basic_table_size = 0; |
JimCarver | 0:6b753f761943 | 188 | uint32_t sector_map_table_addr = NULL; |
JimCarver | 0:6b753f761943 | 189 | size_t sector_map_table_size = 0; |
JimCarver | 0:6b753f761943 | 190 | if ( 0 != _sfdpParseSFDPHeaders(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) { |
JimCarver | 0:6b753f761943 | 191 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Parse SFDP Headers Failed"); |
JimCarver | 0:6b753f761943 | 192 | return BD_ERROR_DEVICE_ERROR; |
JimCarver | 0:6b753f761943 | 193 | } |
JimCarver | 0:6b753f761943 | 194 | |
JimCarver | 0:6b753f761943 | 195 | |
JimCarver | 0:6b753f761943 | 196 | /**************************** Parse Basic Parameters Table ***********************************/ |
JimCarver | 0:6b753f761943 | 197 | if ( 0 != _sfdpParseBasicParamTable(basic_table_addr, basic_table_size) ) { |
JimCarver | 0:6b753f761943 | 198 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Parse Basic Param Table Failed"); |
JimCarver | 0:6b753f761943 | 199 | return BD_ERROR_DEVICE_ERROR; |
JimCarver | 0:6b753f761943 | 200 | } |
JimCarver | 0:6b753f761943 | 201 | |
JimCarver | 0:6b753f761943 | 202 | |
JimCarver | 0:6b753f761943 | 203 | /**************************** Parse Sector Map Table ***********************************/ |
JimCarver | 0:6b753f761943 | 204 | _region_size_bytes[0] = |
JimCarver | 0:6b753f761943 | 205 | _deviceSizeBytes; // If there's no region map, we have a single region sized the entire device size |
JimCarver | 0:6b753f761943 | 206 | _region_high_boundary[0] = _deviceSizeBytes - 1; |
JimCarver | 0:6b753f761943 | 207 | |
JimCarver | 0:6b753f761943 | 208 | if ( (sector_map_table_addr != NULL) && (0 != sector_map_table_size) ) { |
JimCarver | 0:6b753f761943 | 209 | QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - Parsing Sector Map Table - addr: 0x%xh, Size: %d", sector_map_table_addr, |
JimCarver | 0:6b753f761943 | 210 | sector_map_table_size); |
JimCarver | 0:6b753f761943 | 211 | if ( 0 != _sfdpParseSectorMapTable(sector_map_table_addr, sector_map_table_size) ) { |
JimCarver | 0:6b753f761943 | 212 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Parse Sector Map Table Failed"); |
JimCarver | 0:6b753f761943 | 213 | return BD_ERROR_DEVICE_ERROR; |
JimCarver | 0:6b753f761943 | 214 | } |
JimCarver | 0:6b753f761943 | 215 | } |
JimCarver | 0:6b753f761943 | 216 | |
JimCarver | 0:6b753f761943 | 217 | |
JimCarver | 0:6b753f761943 | 218 | // Configure BUS Mode to 1_1_1 for all commands other than Read |
JimCarver | 0:6b753f761943 | 219 | _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, |
JimCarver | 0:6b753f761943 | 220 | QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0); |
JimCarver | 0:6b753f761943 | 221 | /*// Soft Reset |
JimCarver | 0:6b753f761943 | 222 | if( -1 == _resetFlashMem()) { |
JimCarver | 0:6b753f761943 | 223 | QSPIF_LOG(QSPIF_DEBUG_INFO,"ERROR: init - Unable to initialize flash memory, tests failed\n"); |
JimCarver | 0:6b753f761943 | 224 | return -1; |
JimCarver | 0:6b753f761943 | 225 | } else { |
JimCarver | 0:6b753f761943 | 226 | QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: Initialize flash memory OK\n"); |
JimCarver | 0:6b753f761943 | 227 | }*/ |
JimCarver | 0:6b753f761943 | 228 | |
JimCarver | 0:6b753f761943 | 229 | is_initialized = true; |
JimCarver | 0:6b753f761943 | 230 | _mutex->unlock(); |
JimCarver | 0:6b753f761943 | 231 | |
JimCarver | 0:6b753f761943 | 232 | return 0; |
JimCarver | 0:6b753f761943 | 233 | } |
JimCarver | 0:6b753f761943 | 234 | |
JimCarver | 0:6b753f761943 | 235 | int QSPIFBlockDevice::deinit() |
JimCarver | 0:6b753f761943 | 236 | { |
JimCarver | 0:6b753f761943 | 237 | _mutex->lock(); |
JimCarver | 0:6b753f761943 | 238 | if (is_initialized == false) { |
JimCarver | 0:6b753f761943 | 239 | _mutex->unlock(); |
JimCarver | 0:6b753f761943 | 240 | return 0; |
JimCarver | 0:6b753f761943 | 241 | } |
JimCarver | 0:6b753f761943 | 242 | qspi_status_t status = _qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0); |
JimCarver | 0:6b753f761943 | 243 | int result = 0; |
JimCarver | 0:6b753f761943 | 244 | |
JimCarver | 0:6b753f761943 | 245 | if (status != QSPI_STATUS_OK) { |
JimCarver | 0:6b753f761943 | 246 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write Disable failed"); |
JimCarver | 0:6b753f761943 | 247 | result = -1; |
JimCarver | 0:6b753f761943 | 248 | } |
JimCarver | 0:6b753f761943 | 249 | is_initialized = false; |
JimCarver | 0:6b753f761943 | 250 | _mutex->unlock(); |
JimCarver | 0:6b753f761943 | 251 | |
JimCarver | 0:6b753f761943 | 252 | return result; |
JimCarver | 0:6b753f761943 | 253 | } |
JimCarver | 0:6b753f761943 | 254 | |
JimCarver | 0:6b753f761943 | 255 | |
JimCarver | 0:6b753f761943 | 256 | int QSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) |
JimCarver | 0:6b753f761943 | 257 | { |
JimCarver | 0:6b753f761943 | 258 | |
JimCarver | 0:6b753f761943 | 259 | |
JimCarver | 0:6b753f761943 | 260 | int status = 0; |
JimCarver | 0:6b753f761943 | 261 | |
JimCarver | 0:6b753f761943 | 262 | QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO Inst: 0x%xh", _readInstruction); |
JimCarver | 0:6b753f761943 | 263 | |
JimCarver | 0:6b753f761943 | 264 | _mutex->lock(); |
JimCarver | 0:6b753f761943 | 265 | |
JimCarver | 0:6b753f761943 | 266 | _qspiConfiureFormat( |
JimCarver | 0:6b753f761943 | 267 | _inst_width, //Bus width for Instruction phase |
JimCarver | 0:6b753f761943 | 268 | _address_width, //Bus width for Address phase |
JimCarver | 0:6b753f761943 | 269 | _address_size, |
JimCarver | 0:6b753f761943 | 270 | _alt_width, //Bus width for Alt phase |
JimCarver | 0:6b753f761943 | 271 | _alt_size, |
JimCarver | 0:6b753f761943 | 272 | _data_width, //Bus width for Data phase |
JimCarver | 0:6b753f761943 | 273 | _dummy_and_mode_cycles); |
JimCarver | 0:6b753f761943 | 274 | //_qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8); |
JimCarver | 0:6b753f761943 | 275 | |
JimCarver | 0:6b753f761943 | 276 | if (QSPI_STATUS_OK != _qspiSendReadCommand(_readInstruction, buffer, addr, size)) { |
JimCarver | 0:6b753f761943 | 277 | status = -1; |
JimCarver | 0:6b753f761943 | 278 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Read failed\n"); |
JimCarver | 0:6b753f761943 | 279 | } |
JimCarver | 0:6b753f761943 | 280 | |
JimCarver | 0:6b753f761943 | 281 | // All commands other than Read use default 1-1-1 Bus mode (Program/Erase are constrained by flash memory performance less than that of the bus) |
JimCarver | 0:6b753f761943 | 282 | _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, |
JimCarver | 0:6b753f761943 | 283 | QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0); |
JimCarver | 0:6b753f761943 | 284 | |
JimCarver | 0:6b753f761943 | 285 | _mutex->unlock(); |
JimCarver | 0:6b753f761943 | 286 | return status; |
JimCarver | 0:6b753f761943 | 287 | |
JimCarver | 0:6b753f761943 | 288 | } |
JimCarver | 0:6b753f761943 | 289 | |
JimCarver | 0:6b753f761943 | 290 | |
JimCarver | 0:6b753f761943 | 291 | |
JimCarver | 0:6b753f761943 | 292 | |
JimCarver | 0:6b753f761943 | 293 | int QSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) |
JimCarver | 0:6b753f761943 | 294 | { |
JimCarver | 0:6b753f761943 | 295 | qspi_status_t result = QSPI_STATUS_OK; |
JimCarver | 0:6b753f761943 | 296 | bool program_failed = false; |
JimCarver | 0:6b753f761943 | 297 | int status = 0; |
JimCarver | 0:6b753f761943 | 298 | uint32_t offset = 0; |
JimCarver | 0:6b753f761943 | 299 | uint32_t chunk = 0; |
JimCarver | 0:6b753f761943 | 300 | bd_size_t writtenBytes = 0; |
JimCarver | 0:6b753f761943 | 301 | |
JimCarver | 0:6b753f761943 | 302 | while (size > 0) { |
JimCarver | 0:6b753f761943 | 303 | |
JimCarver | 0:6b753f761943 | 304 | // Write on _pageSizeBytes boundaries (Default 256 bytes a page) |
JimCarver | 0:6b753f761943 | 305 | offset = addr % _pageSizeBytes; |
JimCarver | 0:6b753f761943 | 306 | chunk = (offset + size < _pageSizeBytes) ? size : (_pageSizeBytes - offset); |
JimCarver | 0:6b753f761943 | 307 | writtenBytes = chunk; |
JimCarver | 0:6b753f761943 | 308 | |
JimCarver | 0:6b753f761943 | 309 | _mutex->lock(); |
JimCarver | 0:6b753f761943 | 310 | |
JimCarver | 0:6b753f761943 | 311 | //Send WREN |
JimCarver | 0:6b753f761943 | 312 | if (_setWriteEnable() != 0) { |
JimCarver | 0:6b753f761943 | 313 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write Enabe failed\n"); |
JimCarver | 0:6b753f761943 | 314 | program_failed = true; |
JimCarver | 0:6b753f761943 | 315 | goto Exit_Point; |
JimCarver | 0:6b753f761943 | 316 | } |
JimCarver | 0:6b753f761943 | 317 | |
JimCarver | 0:6b753f761943 | 318 | if ( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 319 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready, write failed\n"); |
JimCarver | 0:6b753f761943 | 320 | program_failed = true; |
JimCarver | 0:6b753f761943 | 321 | goto Exit_Point; |
JimCarver | 0:6b753f761943 | 322 | } |
JimCarver | 0:6b753f761943 | 323 | |
JimCarver | 0:6b753f761943 | 324 | result = _qspiSendProgramCommand(_progInstruction, buffer, addr, &writtenBytes); |
JimCarver | 0:6b753f761943 | 325 | if ( (result != QSPI_STATUS_OK) || (chunk != writtenBytes) ) { |
JimCarver | 0:6b753f761943 | 326 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write failed"); |
JimCarver | 0:6b753f761943 | 327 | program_failed = true; |
JimCarver | 0:6b753f761943 | 328 | goto Exit_Point; |
JimCarver | 0:6b753f761943 | 329 | } |
JimCarver | 0:6b753f761943 | 330 | |
JimCarver | 0:6b753f761943 | 331 | buffer = static_cast<const uint8_t *>(buffer) + chunk; |
JimCarver | 0:6b753f761943 | 332 | addr += chunk; |
JimCarver | 0:6b753f761943 | 333 | size -= chunk; |
JimCarver | 0:6b753f761943 | 334 | |
JimCarver | 0:6b753f761943 | 335 | wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC); |
JimCarver | 0:6b753f761943 | 336 | |
JimCarver | 0:6b753f761943 | 337 | if ( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 338 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready after write, failed\n"); |
JimCarver | 0:6b753f761943 | 339 | program_failed = true; |
JimCarver | 0:6b753f761943 | 340 | goto Exit_Point; |
JimCarver | 0:6b753f761943 | 341 | } |
JimCarver | 0:6b753f761943 | 342 | _mutex->unlock(); |
JimCarver | 0:6b753f761943 | 343 | |
JimCarver | 0:6b753f761943 | 344 | |
JimCarver | 0:6b753f761943 | 345 | } |
JimCarver | 0:6b753f761943 | 346 | |
JimCarver | 0:6b753f761943 | 347 | Exit_Point: |
JimCarver | 0:6b753f761943 | 348 | if (program_failed) { |
JimCarver | 0:6b753f761943 | 349 | _mutex->unlock(); |
JimCarver | 0:6b753f761943 | 350 | status = -1; |
JimCarver | 0:6b753f761943 | 351 | } |
JimCarver | 0:6b753f761943 | 352 | |
JimCarver | 0:6b753f761943 | 353 | return status; |
JimCarver | 0:6b753f761943 | 354 | } |
JimCarver | 0:6b753f761943 | 355 | |
JimCarver | 0:6b753f761943 | 356 | |
JimCarver | 0:6b753f761943 | 357 | int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t inSize) |
JimCarver | 0:6b753f761943 | 358 | { |
JimCarver | 0:6b753f761943 | 359 | |
JimCarver | 0:6b753f761943 | 360 | int type = 0; |
JimCarver | 0:6b753f761943 | 361 | uint32_t chunk = 4096; |
JimCarver | 0:6b753f761943 | 362 | unsigned int curEraseInst = _eraseInstruction; |
JimCarver | 0:6b753f761943 | 363 | int size = (int)inSize; |
JimCarver | 0:6b753f761943 | 364 | bool erase_failed = false; |
JimCarver | 0:6b753f761943 | 365 | int status = 0; |
JimCarver | 0:6b753f761943 | 366 | // Find region of erased address |
JimCarver | 0:6b753f761943 | 367 | int region = _utilsFindAddrRegion((int)addr); |
JimCarver | 0:6b753f761943 | 368 | // Erase Types of selected region |
JimCarver | 0:6b753f761943 | 369 | uint8_t bitfield = _region_erase_types[region]; |
JimCarver | 0:6b753f761943 | 370 | |
JimCarver | 0:6b753f761943 | 371 | |
JimCarver | 0:6b753f761943 | 372 | while (size > 0) { |
JimCarver | 0:6b753f761943 | 373 | |
JimCarver | 0:6b753f761943 | 374 | // iterate to find next Largest erase type (1) supported by region, 2) smaller than size) |
JimCarver | 0:6b753f761943 | 375 | // find the matching instruction and erase size chunk for that type. |
JimCarver | 0:6b753f761943 | 376 | type = _utilsIterateNextLargestEraseType(bitfield, (int)size, (int)addr, _region_high_boundary[region]); |
JimCarver | 0:6b753f761943 | 377 | curEraseInst = _eraseTypeInstArr[type]; |
JimCarver | 0:6b753f761943 | 378 | chunk = _eraseTypeSizeArr[type]; |
JimCarver | 0:6b753f761943 | 379 | |
JimCarver | 0:6b753f761943 | 380 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, " Debug: addr: 0x%xh, size:%d, Inst: 0x%xh, chunk: %d , ", |
JimCarver | 0:6b753f761943 | 381 | (int)addr, (int)size, curEraseInst, chunk); |
JimCarver | 0:6b753f761943 | 382 | |
JimCarver | 0:6b753f761943 | 383 | _mutex->lock(); |
JimCarver | 0:6b753f761943 | 384 | |
JimCarver | 0:6b753f761943 | 385 | if (_setWriteEnable() != 0) { |
JimCarver | 0:6b753f761943 | 386 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase - Write Enable failed"); |
JimCarver | 0:6b753f761943 | 387 | erase_failed = true; |
JimCarver | 0:6b753f761943 | 388 | goto Exit_Point; |
JimCarver | 0:6b753f761943 | 389 | } |
JimCarver | 0:6b753f761943 | 390 | |
JimCarver | 0:6b753f761943 | 391 | if ( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 392 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase Device not ready - failed"); |
JimCarver | 0:6b753f761943 | 393 | erase_failed = true; |
JimCarver | 0:6b753f761943 | 394 | goto Exit_Point; |
JimCarver | 0:6b753f761943 | 395 | } |
JimCarver | 0:6b753f761943 | 396 | |
JimCarver | 0:6b753f761943 | 397 | if (QSPI_STATUS_OK != _qspiSendEraseCommand(curEraseInst, addr, size) ) { |
JimCarver | 0:6b753f761943 | 398 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase command failed!"); |
JimCarver | 0:6b753f761943 | 399 | erase_failed = true; |
JimCarver | 0:6b753f761943 | 400 | goto Exit_Point; |
JimCarver | 0:6b753f761943 | 401 | } |
JimCarver | 0:6b753f761943 | 402 | |
JimCarver | 0:6b753f761943 | 403 | addr += chunk; |
JimCarver | 0:6b753f761943 | 404 | size -= chunk; |
JimCarver | 0:6b753f761943 | 405 | |
JimCarver | 0:6b753f761943 | 406 | if ( (size > 0) && (addr > _region_high_boundary[region]) ) { |
JimCarver | 0:6b753f761943 | 407 | // erase crossed to next region |
JimCarver | 0:6b753f761943 | 408 | region++; |
JimCarver | 0:6b753f761943 | 409 | bitfield = _region_erase_types[region]; |
JimCarver | 0:6b753f761943 | 410 | } |
JimCarver | 0:6b753f761943 | 411 | wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC); |
JimCarver | 0:6b753f761943 | 412 | if ( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 413 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI After Erase Device not ready - failed\n"); |
JimCarver | 0:6b753f761943 | 414 | erase_failed = true; |
JimCarver | 0:6b753f761943 | 415 | goto Exit_Point; |
JimCarver | 0:6b753f761943 | 416 | } |
JimCarver | 0:6b753f761943 | 417 | _mutex->unlock(); |
JimCarver | 0:6b753f761943 | 418 | |
JimCarver | 0:6b753f761943 | 419 | } |
JimCarver | 0:6b753f761943 | 420 | |
JimCarver | 0:6b753f761943 | 421 | |
JimCarver | 0:6b753f761943 | 422 | Exit_Point: |
JimCarver | 0:6b753f761943 | 423 | if (erase_failed) { |
JimCarver | 0:6b753f761943 | 424 | _mutex->unlock(); |
JimCarver | 0:6b753f761943 | 425 | status = -1; |
JimCarver | 0:6b753f761943 | 426 | } |
JimCarver | 0:6b753f761943 | 427 | |
JimCarver | 0:6b753f761943 | 428 | return status; |
JimCarver | 0:6b753f761943 | 429 | } |
JimCarver | 0:6b753f761943 | 430 | |
JimCarver | 0:6b753f761943 | 431 | |
JimCarver | 0:6b753f761943 | 432 | |
JimCarver | 0:6b753f761943 | 433 | bd_size_t QSPIFBlockDevice::get_read_size() const |
JimCarver | 0:6b753f761943 | 434 | { |
JimCarver | 0:6b753f761943 | 435 | return QSPIF_DEFAULT_READ_SIZE; |
JimCarver | 0:6b753f761943 | 436 | } |
JimCarver | 0:6b753f761943 | 437 | |
JimCarver | 0:6b753f761943 | 438 | bd_size_t QSPIFBlockDevice::get_program_size() const |
JimCarver | 0:6b753f761943 | 439 | { |
JimCarver | 0:6b753f761943 | 440 | return QSPIF_DEFAULT_PROG_SIZE; |
JimCarver | 0:6b753f761943 | 441 | } |
JimCarver | 0:6b753f761943 | 442 | |
JimCarver | 0:6b753f761943 | 443 | bd_size_t QSPIFBlockDevice::get_erase_size() const |
JimCarver | 0:6b753f761943 | 444 | { |
JimCarver | 0:6b753f761943 | 445 | return _minCommonEraseSize; |
JimCarver | 0:6b753f761943 | 446 | } |
JimCarver | 0:6b753f761943 | 447 | |
JimCarver | 0:6b753f761943 | 448 | |
JimCarver | 0:6b753f761943 | 449 | // Find minimal erase size supported by address region |
JimCarver | 0:6b753f761943 | 450 | bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr) |
JimCarver | 0:6b753f761943 | 451 | { |
JimCarver | 0:6b753f761943 | 452 | // Find region of current address |
JimCarver | 0:6b753f761943 | 453 | int region = _utilsFindAddrRegion((int)addr); |
JimCarver | 0:6b753f761943 | 454 | |
JimCarver | 0:6b753f761943 | 455 | int minRegionEraseSize = _minCommonEraseSize; |
JimCarver | 0:6b753f761943 | 456 | int8_t type_mask = 0x01; |
JimCarver | 0:6b753f761943 | 457 | int i_ind = 0; |
JimCarver | 0:6b753f761943 | 458 | |
JimCarver | 0:6b753f761943 | 459 | if (region != -1) { |
JimCarver | 0:6b753f761943 | 460 | type_mask = 0x01; |
JimCarver | 0:6b753f761943 | 461 | |
JimCarver | 0:6b753f761943 | 462 | for (i_ind = 0; i_ind < 4; i_ind++) { |
JimCarver | 0:6b753f761943 | 463 | // loop through erase types supported by region |
JimCarver | 0:6b753f761943 | 464 | if (_region_erase_types[region] & type_mask) { |
JimCarver | 0:6b753f761943 | 465 | |
JimCarver | 0:6b753f761943 | 466 | minRegionEraseSize = _eraseTypeSizeArr[i_ind]; |
JimCarver | 0:6b753f761943 | 467 | break; |
JimCarver | 0:6b753f761943 | 468 | } |
JimCarver | 0:6b753f761943 | 469 | type_mask = type_mask << 1; |
JimCarver | 0:6b753f761943 | 470 | } |
JimCarver | 0:6b753f761943 | 471 | |
JimCarver | 0:6b753f761943 | 472 | if (i_ind == 4) { |
JimCarver | 0:6b753f761943 | 473 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: no erase type was found for region addr"); |
JimCarver | 0:6b753f761943 | 474 | } |
JimCarver | 0:6b753f761943 | 475 | } |
JimCarver | 0:6b753f761943 | 476 | |
JimCarver | 0:6b753f761943 | 477 | return (bd_size_t)minRegionEraseSize; |
JimCarver | 0:6b753f761943 | 478 | |
JimCarver | 0:6b753f761943 | 479 | } |
JimCarver | 0:6b753f761943 | 480 | |
JimCarver | 0:6b753f761943 | 481 | bd_size_t QSPIFBlockDevice::size() const |
JimCarver | 0:6b753f761943 | 482 | { |
JimCarver | 0:6b753f761943 | 483 | return _deviceSizeBytes; |
JimCarver | 0:6b753f761943 | 484 | } |
JimCarver | 0:6b753f761943 | 485 | |
JimCarver | 0:6b753f761943 | 486 | |
JimCarver | 0:6b753f761943 | 487 | /*********************************************************/ |
JimCarver | 0:6b753f761943 | 488 | /********** SFDP Parsing and Detection Functions *********/ |
JimCarver | 0:6b753f761943 | 489 | /*********************************************************/ |
JimCarver | 0:6b753f761943 | 490 | |
JimCarver | 0:6b753f761943 | 491 | int QSPIFBlockDevice::_sfdpParseSectorMapTable(uint32_t sector_map_table_addr, size_t sector_map_table_size) |
JimCarver | 0:6b753f761943 | 492 | { |
JimCarver | 0:6b753f761943 | 493 | uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */ |
JimCarver | 0:6b753f761943 | 494 | uint32_t tmpRegionSize = 0; |
JimCarver | 0:6b753f761943 | 495 | int i_ind = 0; |
JimCarver | 0:6b753f761943 | 496 | int prevBoundary = 0; |
JimCarver | 0:6b753f761943 | 497 | // Default set to all type bits 1-4 are common |
JimCarver | 0:6b753f761943 | 498 | _minCommonEraseType = 0x0F; |
JimCarver | 0:6b753f761943 | 499 | |
JimCarver | 0:6b753f761943 | 500 | qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sector_map_table, sector_map_table_addr /*address*/, |
JimCarver | 0:6b753f761943 | 501 | sector_map_table_size); |
JimCarver | 0:6b753f761943 | 502 | if (status != QSPI_STATUS_OK) { |
JimCarver | 0:6b753f761943 | 503 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read SFDP First Table Failed"); |
JimCarver | 0:6b753f761943 | 504 | return -1; |
JimCarver | 0:6b753f761943 | 505 | } |
JimCarver | 0:6b753f761943 | 506 | |
JimCarver | 0:6b753f761943 | 507 | //QSPIF_LOG(QSPIF_DEBUG_DEBUG,\nDEBUG: "Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n",sector_map_table[0], |
JimCarver | 0:6b753f761943 | 508 | // sector_map_table[1], |
JimCarver | 0:6b753f761943 | 509 | // sector_map_table[2], |
JimCarver | 0:6b753f761943 | 510 | // sector_map_table[3], |
JimCarver | 0:6b753f761943 | 511 | // sector_map_table[4], |
JimCarver | 0:6b753f761943 | 512 | // sector_map_table[5], |
JimCarver | 0:6b753f761943 | 513 | // sector_map_table[6], |
JimCarver | 0:6b753f761943 | 514 | // sector_map_table[7], sector_map_table[56], sector_map_table[57], sector_map_table[58], sector_map_table[59], sector_map_table[52]); |
JimCarver | 0:6b753f761943 | 515 | |
JimCarver | 0:6b753f761943 | 516 | // Currently we support only Single Map Descriptor |
JimCarver | 0:6b753f761943 | 517 | if (! ( (sector_map_table[0] & 0x3) == 0x03 ) && (sector_map_table[1] == 0x0) ) { |
JimCarver | 0:6b753f761943 | 518 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Sector Map - Supporting Only Single! Map Descriptor (not map commands)"); |
JimCarver | 0:6b753f761943 | 519 | return -1; |
JimCarver | 0:6b753f761943 | 520 | } |
JimCarver | 0:6b753f761943 | 521 | |
JimCarver | 0:6b753f761943 | 522 | _regions_count = sector_map_table[2] + 1; |
JimCarver | 0:6b753f761943 | 523 | if (_regions_count > QSPIF_MAX_REGIONS) { |
JimCarver | 0:6b753f761943 | 524 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Supporting up to %d regions, current setup to %d regions - fail", |
JimCarver | 0:6b753f761943 | 525 | QSPIF_MAX_REGIONS, _regions_count); |
JimCarver | 0:6b753f761943 | 526 | return -1; |
JimCarver | 0:6b753f761943 | 527 | } |
JimCarver | 0:6b753f761943 | 528 | |
JimCarver | 0:6b753f761943 | 529 | // Loop through Regions and set for each one: size, supported erase types, high boundary offset |
JimCarver | 0:6b753f761943 | 530 | // Calculate minimum Common Erase Type for all Regions |
JimCarver | 0:6b753f761943 | 531 | for (i_ind = 0; i_ind < _regions_count; i_ind++) { |
JimCarver | 0:6b753f761943 | 532 | tmpRegionSize = ((*((uint32_t *)§or_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32 |
JimCarver | 0:6b753f761943 | 533 | _region_size_bytes[i_ind] = (tmpRegionSize + 1) * 256; // Region size is 0 based multiple of 256 bytes; |
JimCarver | 0:6b753f761943 | 534 | _region_erase_types[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4 |
JimCarver | 0:6b753f761943 | 535 | _minCommonEraseType &= _region_erase_types[i_ind]; |
JimCarver | 0:6b753f761943 | 536 | _region_high_boundary[i_ind] = (_region_size_bytes[i_ind] - 1) + prevBoundary; |
JimCarver | 0:6b753f761943 | 537 | prevBoundary = _region_high_boundary[i_ind] + 1; |
JimCarver | 0:6b753f761943 | 538 | } |
JimCarver | 0:6b753f761943 | 539 | |
JimCarver | 0:6b753f761943 | 540 | // Calc minimum Common Erase Size from _minCommonEraseType |
JimCarver | 0:6b753f761943 | 541 | uint8_t type_mask = 0x01; |
JimCarver | 0:6b753f761943 | 542 | for (i_ind = 0; i_ind < 4; i_ind++) { |
JimCarver | 0:6b753f761943 | 543 | if (_minCommonEraseType & type_mask) { |
JimCarver | 0:6b753f761943 | 544 | _minCommonEraseType = i_ind; |
JimCarver | 0:6b753f761943 | 545 | _minCommonEraseSize = _eraseTypeSizeArr[i_ind]; |
JimCarver | 0:6b753f761943 | 546 | break; |
JimCarver | 0:6b753f761943 | 547 | } |
JimCarver | 0:6b753f761943 | 548 | type_mask = type_mask << 1; |
JimCarver | 0:6b753f761943 | 549 | } |
JimCarver | 0:6b753f761943 | 550 | |
JimCarver | 0:6b753f761943 | 551 | if (i_ind == 4) { |
JimCarver | 0:6b753f761943 | 552 | // No common erase type was found between regions |
JimCarver | 0:6b753f761943 | 553 | _minCommonEraseType = 0; |
JimCarver | 0:6b753f761943 | 554 | _minCommonEraseSize = -1; |
JimCarver | 0:6b753f761943 | 555 | } |
JimCarver | 0:6b753f761943 | 556 | |
JimCarver | 0:6b753f761943 | 557 | return 0; |
JimCarver | 0:6b753f761943 | 558 | } |
JimCarver | 0:6b753f761943 | 559 | |
JimCarver | 0:6b753f761943 | 560 | |
JimCarver | 0:6b753f761943 | 561 | int QSPIFBlockDevice::_sfdpParseBasicParamTable(uint32_t basic_table_addr, size_t basic_table_size) |
JimCarver | 0:6b753f761943 | 562 | { |
JimCarver | 0:6b753f761943 | 563 | uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */ |
JimCarver | 0:6b753f761943 | 564 | |
JimCarver | 0:6b753f761943 | 565 | qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_table, basic_table_addr /*address*/, |
JimCarver | 0:6b753f761943 | 566 | basic_table_size); |
JimCarver | 0:6b753f761943 | 567 | if (status != QSPI_STATUS_OK) { |
JimCarver | 0:6b753f761943 | 568 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read SFDP First Table Failed, Status %d",status); |
JimCarver | 0:6b753f761943 | 569 | return -1; |
JimCarver | 0:6b753f761943 | 570 | } |
JimCarver | 0:6b753f761943 | 571 | |
JimCarver | 0:6b753f761943 | 572 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n", |
JimCarver | 0:6b753f761943 | 573 | param_table[0], |
JimCarver | 0:6b753f761943 | 574 | param_table[1], |
JimCarver | 0:6b753f761943 | 575 | param_table[2], |
JimCarver | 0:6b753f761943 | 576 | param_table[3], |
JimCarver | 0:6b753f761943 | 577 | param_table[4], |
JimCarver | 0:6b753f761943 | 578 | param_table[5], |
JimCarver | 0:6b753f761943 | 579 | param_table[6], |
JimCarver | 0:6b753f761943 | 580 | param_table[7], param_table[56], param_table[57], param_table[58], param_table[59], param_table[52]); |
JimCarver | 0:6b753f761943 | 581 | |
JimCarver | 0:6b753f761943 | 582 | |
JimCarver | 0:6b753f761943 | 583 | // Check address size, currently only supports 3byte addresses |
JimCarver | 0:6b753f761943 | 584 | if ((param_table[2] & 0x4) != 0 || (param_table[7] & 0x80) != 0) { |
JimCarver | 0:6b753f761943 | 585 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - verify 3byte addressing Failed"); |
JimCarver | 0:6b753f761943 | 586 | return -1; |
JimCarver | 0:6b753f761943 | 587 | } |
JimCarver | 0:6b753f761943 | 588 | |
JimCarver | 0:6b753f761943 | 589 | // Get device density (stored in bits - 1) |
JimCarver | 0:6b753f761943 | 590 | uint32_t density_bits = ( |
JimCarver | 0:6b753f761943 | 591 | (param_table[7] << 24) | |
JimCarver | 0:6b753f761943 | 592 | (param_table[6] << 16) | |
JimCarver | 0:6b753f761943 | 593 | (param_table[5] << 8 ) | |
JimCarver | 0:6b753f761943 | 594 | param_table[4] ); |
JimCarver | 0:6b753f761943 | 595 | _deviceSizeBytes = (density_bits + 1) / 8; |
JimCarver | 0:6b753f761943 | 596 | |
JimCarver | 0:6b753f761943 | 597 | // Set Default read/program/erase Instructions |
JimCarver | 0:6b753f761943 | 598 | _readInstruction = QSPIF_READ; |
JimCarver | 0:6b753f761943 | 599 | _progInstruction = QSPIF_PP; |
JimCarver | 0:6b753f761943 | 600 | _eraseInstruction = QSPIF_SE; |
JimCarver | 0:6b753f761943 | 601 | |
JimCarver | 0:6b753f761943 | 602 | // Set Page Size (QSPI write must be done on Page limits) |
JimCarver | 0:6b753f761943 | 603 | _pageSizeBytes = _sfdpDetectPageSize(param_table); |
JimCarver | 0:6b753f761943 | 604 | |
JimCarver | 0:6b753f761943 | 605 | // Detect and Set Erase Types |
JimCarver | 0:6b753f761943 | 606 | bool shouldSetQuadEnable = false; |
JimCarver | 0:6b753f761943 | 607 | bool isQPIMode = false; |
JimCarver | 0:6b753f761943 | 608 | _sfdpDetectEraseTypesInstAndSize(param_table, _erase4KInst, _eraseTypeInstArr, _eraseTypeSizeArr); |
JimCarver | 0:6b753f761943 | 609 | _eraseInstruction = _erase4KInst; |
JimCarver | 0:6b753f761943 | 610 | |
JimCarver | 0:6b753f761943 | 611 | |
JimCarver | 0:6b753f761943 | 612 | // Detect and Set fastest Bus mode (default 1-1-1) |
JimCarver | 0:6b753f761943 | 613 | _sfdpDetectBestBusReadMode(param_table, shouldSetQuadEnable, isQPIMode, _readInstruction); |
JimCarver | 0:6b753f761943 | 614 | |
JimCarver | 0:6b753f761943 | 615 | if (true == shouldSetQuadEnable) { |
JimCarver | 0:6b753f761943 | 616 | // Set Quad Enable and QPI Bus modes if Supported |
JimCarver | 0:6b753f761943 | 617 | QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - Setting Quad Enable"); |
JimCarver | 0:6b753f761943 | 618 | _sfdpSetQuadEnabled(param_table); |
JimCarver | 0:6b753f761943 | 619 | if (true == isQPIMode) { |
JimCarver | 0:6b753f761943 | 620 | QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - Setting QPI mode"); |
JimCarver | 0:6b753f761943 | 621 | _sfdpSetQPIEnabled(param_table); |
JimCarver | 0:6b753f761943 | 622 | } |
JimCarver | 0:6b753f761943 | 623 | } |
JimCarver | 0:6b753f761943 | 624 | return 0; |
JimCarver | 0:6b753f761943 | 625 | } |
JimCarver | 0:6b753f761943 | 626 | |
JimCarver | 0:6b753f761943 | 627 | int QSPIFBlockDevice::_sfdpParseSFDPHeaders(uint32_t& basic_table_addr, size_t& basic_table_size, |
JimCarver | 0:6b753f761943 | 628 | uint32_t& sector_map_table_addr, size_t& sector_map_table_size) |
JimCarver | 0:6b753f761943 | 629 | { |
JimCarver | 0:6b753f761943 | 630 | uint8_t sfdp_header[QSPIF_SFDP_HEADER_SIZE]; |
JimCarver | 0:6b753f761943 | 631 | uint8_t param_header[QSPIF_PARAM_HEADER_SIZE]; |
JimCarver | 0:6b753f761943 | 632 | size_t data_length = QSPIF_SFDP_HEADER_SIZE; |
JimCarver | 0:6b753f761943 | 633 | bd_addr_t addr = 0x0; |
JimCarver | 0:6b753f761943 | 634 | |
JimCarver | 0:6b753f761943 | 635 | // Set 1-1-1 bus mode for SFDP header parsing |
JimCarver | 0:6b753f761943 | 636 | _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, |
JimCarver | 0:6b753f761943 | 637 | QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8); |
JimCarver | 0:6b753f761943 | 638 | |
JimCarver | 0:6b753f761943 | 639 | qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sfdp_header, addr /*address*/, data_length); |
JimCarver | 0:6b753f761943 | 640 | if (status != QSPI_STATUS_OK) { |
JimCarver | 0:6b753f761943 | 641 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read SFDP Failed"); |
JimCarver | 0:6b753f761943 | 642 | return -1; |
JimCarver | 0:6b753f761943 | 643 | } |
JimCarver | 0:6b753f761943 | 644 | |
JimCarver | 0:6b753f761943 | 645 | |
JimCarver | 0:6b753f761943 | 646 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG11: Read SFDP Header: %x %x %x %x %x %x %x %x\n", sfdp_header[0], |
JimCarver | 0:6b753f761943 | 647 | sfdp_header[1], |
JimCarver | 0:6b753f761943 | 648 | sfdp_header[2], |
JimCarver | 0:6b753f761943 | 649 | sfdp_header[3], |
JimCarver | 0:6b753f761943 | 650 | sfdp_header[4], |
JimCarver | 0:6b753f761943 | 651 | sfdp_header[5], |
JimCarver | 0:6b753f761943 | 652 | sfdp_header[6], |
JimCarver | 0:6b753f761943 | 653 | sfdp_header[7]); |
JimCarver | 0:6b753f761943 | 654 | |
JimCarver | 0:6b753f761943 | 655 | |
JimCarver | 0:6b753f761943 | 656 | // Verify SFDP signature for sanity |
JimCarver | 0:6b753f761943 | 657 | // Also check that major/minor version is acceptable |
JimCarver | 0:6b753f761943 | 658 | if (!(memcmp(&sfdp_header[0], "SFDP", 4) == 0 && sfdp_header[5] == 1)) { |
JimCarver | 0:6b753f761943 | 659 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - _verify SFDP signature and version Failed"); |
JimCarver | 0:6b753f761943 | 660 | return -1; |
JimCarver | 0:6b753f761943 | 661 | } else { |
JimCarver | 0:6b753f761943 | 662 | QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - verified SFDP Signature and version Successfully"); |
JimCarver | 0:6b753f761943 | 663 | } |
JimCarver | 0:6b753f761943 | 664 | |
JimCarver | 0:6b753f761943 | 665 | // Discover Number of Parameter Headers |
JimCarver | 0:6b753f761943 | 666 | int number_of_param_headers = (int)(sfdp_header[6]) + 1; |
JimCarver | 0:6b753f761943 | 667 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: number of Param Headers: %d", number_of_param_headers); |
JimCarver | 0:6b753f761943 | 668 | |
JimCarver | 0:6b753f761943 | 669 | |
JimCarver | 0:6b753f761943 | 670 | addr += QSPIF_SFDP_HEADER_SIZE; |
JimCarver | 0:6b753f761943 | 671 | data_length = QSPIF_PARAM_HEADER_SIZE; |
JimCarver | 0:6b753f761943 | 672 | |
JimCarver | 0:6b753f761943 | 673 | // Loop over Param Headers and parse them (currently supported Basic Param Table and Sector Region Map Table) |
JimCarver | 0:6b753f761943 | 674 | for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) { |
JimCarver | 0:6b753f761943 | 675 | |
JimCarver | 0:6b753f761943 | 676 | status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_header, addr, data_length); |
JimCarver | 0:6b753f761943 | 677 | if (status != QSPI_STATUS_OK) { |
JimCarver | 0:6b753f761943 | 678 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read Param Table %d Failed", i_ind + 1); |
JimCarver | 0:6b753f761943 | 679 | return -1; |
JimCarver | 0:6b753f761943 | 680 | } |
JimCarver | 0:6b753f761943 | 681 | // The SFDP spec indicates the standard table is always at offset 0 |
JimCarver | 0:6b753f761943 | 682 | // in the parameter headers, we check just to be safe |
JimCarver | 0:6b753f761943 | 683 | if (param_header[2] != 1) { |
JimCarver | 0:6b753f761943 | 684 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Param Table %d - Major Version should be 1!", i_ind + 1); |
JimCarver | 0:6b753f761943 | 685 | return -1; |
JimCarver | 0:6b753f761943 | 686 | } |
JimCarver | 0:6b753f761943 | 687 | |
JimCarver | 0:6b753f761943 | 688 | if ((param_header[0] == 0) && (param_header[7] == 0xFF)) { |
JimCarver | 0:6b753f761943 | 689 | // Found Basic Params Table: LSB=0x00, MSB=0xFF |
JimCarver | 0:6b753f761943 | 690 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Found Basic Param Table at Table: %d", i_ind + 1); |
JimCarver | 0:6b753f761943 | 691 | basic_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) ); |
JimCarver | 0:6b753f761943 | 692 | // Supporting up to 64 Bytes Table (16 DWORDS) |
JimCarver | 0:6b753f761943 | 693 | basic_table_size = ((param_header[3] * 4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[11] * 4) : 64; |
JimCarver | 0:6b753f761943 | 694 | |
JimCarver | 0:6b753f761943 | 695 | } else if ((param_header[0] == 81) && (param_header[7] == 0xFF)) { |
JimCarver | 0:6b753f761943 | 696 | // Found Sector Map Table: LSB=0x81, MSB=0xFF |
JimCarver | 0:6b753f761943 | 697 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Found Sector Map Table at Table: %d", i_ind + 1); |
JimCarver | 0:6b753f761943 | 698 | sector_map_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) ); |
JimCarver | 0:6b753f761943 | 699 | |
JimCarver | 0:6b753f761943 | 700 | sector_map_table_size = param_header[3] * 4; |
JimCarver | 0:6b753f761943 | 701 | |
JimCarver | 0:6b753f761943 | 702 | } |
JimCarver | 0:6b753f761943 | 703 | addr += QSPIF_PARAM_HEADER_SIZE; |
JimCarver | 0:6b753f761943 | 704 | |
JimCarver | 0:6b753f761943 | 705 | } |
JimCarver | 0:6b753f761943 | 706 | return 0; |
JimCarver | 0:6b753f761943 | 707 | } |
JimCarver | 0:6b753f761943 | 708 | |
JimCarver | 0:6b753f761943 | 709 | |
JimCarver | 0:6b753f761943 | 710 | |
JimCarver | 0:6b753f761943 | 711 | int QSPIFBlockDevice::_sfdpSetQPIEnabled(uint8_t *basicParamTablePtr) |
JimCarver | 0:6b753f761943 | 712 | { |
JimCarver | 0:6b753f761943 | 713 | uint8_t config_reg[1]; |
JimCarver | 0:6b753f761943 | 714 | |
JimCarver | 0:6b753f761943 | 715 | // QPI 4-4-4 Enable Procedure is specified in 5 Bits |
JimCarver | 0:6b753f761943 | 716 | uint8_t en_seq_444_value = ( ((basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE] & 0xF0) >> 4) | (( |
JimCarver | 0:6b753f761943 | 717 | basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE + 1] & 0x01) << 4 )); |
JimCarver | 0:6b753f761943 | 718 | |
JimCarver | 0:6b753f761943 | 719 | switch (en_seq_444_value) { |
JimCarver | 0:6b753f761943 | 720 | case 1: |
JimCarver | 0:6b753f761943 | 721 | case 2: |
JimCarver | 0:6b753f761943 | 722 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - send command 38h"); |
JimCarver | 0:6b753f761943 | 723 | /*if (_setWriteEnable() != 0) { |
JimCarver | 0:6b753f761943 | 724 | printf("ERROR: Write Enabe failed\n"); |
JimCarver | 0:6b753f761943 | 725 | return -1; |
JimCarver | 0:6b753f761943 | 726 | } |
JimCarver | 0:6b753f761943 | 727 | if( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 728 | printf("ERROR: Device not ready, write failed\n"); |
JimCarver | 0:6b753f761943 | 729 | return -1; |
JimCarver | 0:6b753f761943 | 730 | }*/ |
JimCarver | 0:6b753f761943 | 731 | |
JimCarver | 0:6b753f761943 | 732 | _qspiSendGeneralCommand(0x38, -1, NULL, 0, NULL, 0); |
JimCarver | 0:6b753f761943 | 733 | /*wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC); |
JimCarver | 0:6b753f761943 | 734 | if( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 735 | printf("ERROR: Device not ready after write, failed\n"); |
JimCarver | 0:6b753f761943 | 736 | return -1; |
JimCarver | 0:6b753f761943 | 737 | }*/ |
JimCarver | 0:6b753f761943 | 738 | |
JimCarver | 0:6b753f761943 | 739 | |
JimCarver | 0:6b753f761943 | 740 | break; |
JimCarver | 0:6b753f761943 | 741 | |
JimCarver | 0:6b753f761943 | 742 | case 4: |
JimCarver | 0:6b753f761943 | 743 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - send command 35h"); |
JimCarver | 0:6b753f761943 | 744 | _qspiSendGeneralCommand(0x35, -1, NULL, 0, NULL, 0); |
JimCarver | 0:6b753f761943 | 745 | break; |
JimCarver | 0:6b753f761943 | 746 | |
JimCarver | 0:6b753f761943 | 747 | case 8: |
JimCarver | 0:6b753f761943 | 748 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - set config bit 6 and send command 71h"); |
JimCarver | 0:6b753f761943 | 749 | _qspiSendGeneralCommand(0x65, 0x800003, NULL, 0, (char *)config_reg, 1); |
JimCarver | 0:6b753f761943 | 750 | config_reg[1] |= 0x40; //Set Bit 6 |
JimCarver | 0:6b753f761943 | 751 | _qspiSendGeneralCommand(0x71, 0x800003, NULL, 0, (char *)config_reg, 1); |
JimCarver | 0:6b753f761943 | 752 | break; |
JimCarver | 0:6b753f761943 | 753 | |
JimCarver | 0:6b753f761943 | 754 | case 16: |
JimCarver | 0:6b753f761943 | 755 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - reset config bits 0-7 and send command 61h"); |
JimCarver | 0:6b753f761943 | 756 | _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1); |
JimCarver | 0:6b753f761943 | 757 | config_reg[1] &= 0x7F; //Reset Bit 7 of CR |
JimCarver | 0:6b753f761943 | 758 | |
JimCarver | 0:6b753f761943 | 759 | |
JimCarver | 0:6b753f761943 | 760 | |
JimCarver | 0:6b753f761943 | 761 | |
JimCarver | 0:6b753f761943 | 762 | /* |
JimCarver | 0:6b753f761943 | 763 | if (_setWriteEnable() != 0) { |
JimCarver | 0:6b753f761943 | 764 | printf("ERROR: Write Enabe failed\n"); |
JimCarver | 0:6b753f761943 | 765 | return -1; |
JimCarver | 0:6b753f761943 | 766 | } |
JimCarver | 0:6b753f761943 | 767 | if( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 768 | printf("ERROR: Device not ready, write failed\n"); |
JimCarver | 0:6b753f761943 | 769 | return -1; |
JimCarver | 0:6b753f761943 | 770 | }*/ |
JimCarver | 0:6b753f761943 | 771 | |
JimCarver | 0:6b753f761943 | 772 | _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1); |
JimCarver | 0:6b753f761943 | 773 | |
JimCarver | 0:6b753f761943 | 774 | |
JimCarver | 0:6b753f761943 | 775 | /* wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC); |
JimCarver | 0:6b753f761943 | 776 | if( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 777 | printf("ERROR: Device not ready after write, failed\n"); |
JimCarver | 0:6b753f761943 | 778 | return -1; |
JimCarver | 0:6b753f761943 | 779 | } |
JimCarver | 0:6b753f761943 | 780 | |
JimCarver | 0:6b753f761943 | 781 | |
JimCarver | 0:6b753f761943 | 782 | |
JimCarver | 0:6b753f761943 | 783 | _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1); |
JimCarver | 0:6b753f761943 | 784 | |
JimCarver | 0:6b753f761943 | 785 | if (_setWriteEnable() != 0) { |
JimCarver | 0:6b753f761943 | 786 | printf("ERROR: Write Enabe failed\n"); |
JimCarver | 0:6b753f761943 | 787 | return -1; |
JimCarver | 0:6b753f761943 | 788 | } |
JimCarver | 0:6b753f761943 | 789 | if( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 790 | printf("ERROR: Device not ready, write failed\n"); |
JimCarver | 0:6b753f761943 | 791 | return -1; |
JimCarver | 0:6b753f761943 | 792 | } |
JimCarver | 0:6b753f761943 | 793 | config_reg[1] = 0x00; //Reset Bits 0-7 |
JimCarver | 0:6b753f761943 | 794 | _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1); |
JimCarver | 0:6b753f761943 | 795 | wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);*/ |
JimCarver | 0:6b753f761943 | 796 | /* if( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 797 | printf("ERROR: Device not ready after write, failed\n"); |
JimCarver | 0:6b753f761943 | 798 | return -1; |
JimCarver | 0:6b753f761943 | 799 | }*/ |
JimCarver | 0:6b753f761943 | 800 | |
JimCarver | 0:6b753f761943 | 801 | break; |
JimCarver | 0:6b753f761943 | 802 | |
JimCarver | 0:6b753f761943 | 803 | default: |
JimCarver | 0:6b753f761943 | 804 | QSPIF_LOG(QSPIF_DEBUG_WARNING, "WARNING: _setQPIEnabled - Unsuported En Seq 444 configuration"); |
JimCarver | 0:6b753f761943 | 805 | break; |
JimCarver | 0:6b753f761943 | 806 | |
JimCarver | 0:6b753f761943 | 807 | |
JimCarver | 0:6b753f761943 | 808 | } |
JimCarver | 0:6b753f761943 | 809 | |
JimCarver | 0:6b753f761943 | 810 | return 0; |
JimCarver | 0:6b753f761943 | 811 | } |
JimCarver | 0:6b753f761943 | 812 | |
JimCarver | 0:6b753f761943 | 813 | |
JimCarver | 0:6b753f761943 | 814 | |
JimCarver | 0:6b753f761943 | 815 | int QSPIFBlockDevice::_sfdpSetQuadEnabled(uint8_t *basicParamTablePtr) |
JimCarver | 0:6b753f761943 | 816 | { |
JimCarver | 0:6b753f761943 | 817 | |
JimCarver | 0:6b753f761943 | 818 | int sr_read_size = QSPI_MAX_STATUS_REGISTER_SIZE; |
JimCarver | 0:6b753f761943 | 819 | int sr_write_size = QSPI_MAX_STATUS_REGISTER_SIZE; |
JimCarver | 0:6b753f761943 | 820 | |
JimCarver | 0:6b753f761943 | 821 | int status_reg_setup[QSPI_MAX_STATUS_REGISTER_SIZE]; |
JimCarver | 0:6b753f761943 | 822 | uint8_t status_reg[QSPI_MAX_STATUS_REGISTER_SIZE]; |
JimCarver | 0:6b753f761943 | 823 | unsigned int writeRegisterInst = QSPIF_WRSR; |
JimCarver | 0:6b753f761943 | 824 | unsigned int readRegisterInst = QSPIF_RDSR; |
JimCarver | 0:6b753f761943 | 825 | |
JimCarver | 0:6b753f761943 | 826 | uint8_t qer_value = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QER_BYTE] & 0x70) >> 4; |
JimCarver | 0:6b753f761943 | 827 | |
JimCarver | 0:6b753f761943 | 828 | |
JimCarver | 0:6b753f761943 | 829 | |
JimCarver | 0:6b753f761943 | 830 | switch (qer_value) { |
JimCarver | 0:6b753f761943 | 831 | case 0: |
JimCarver | 0:6b753f761943 | 832 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Device Does not Have a QE Bit, continue based on Read Inst"); |
JimCarver | 0:6b753f761943 | 833 | return 0; |
JimCarver | 0:6b753f761943 | 834 | |
JimCarver | 0:6b753f761943 | 835 | case 1: |
JimCarver | 0:6b753f761943 | 836 | case 4: |
JimCarver | 0:6b753f761943 | 837 | status_reg_setup[0] = 0; |
JimCarver | 0:6b753f761943 | 838 | status_reg_setup[1] = 0x02; |
JimCarver | 0:6b753f761943 | 839 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 1 of Status Reg 2"); |
JimCarver | 0:6b753f761943 | 840 | break; |
JimCarver | 0:6b753f761943 | 841 | |
JimCarver | 0:6b753f761943 | 842 | case 2: |
JimCarver | 0:6b753f761943 | 843 | status_reg_setup[0] = 0x40; |
JimCarver | 0:6b753f761943 | 844 | status_reg_setup[1] = 0; |
JimCarver | 0:6b753f761943 | 845 | sr_write_size = 1; |
JimCarver | 0:6b753f761943 | 846 | sr_read_size = 1; |
JimCarver | 0:6b753f761943 | 847 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 6 of Status Reg 1"); |
JimCarver | 0:6b753f761943 | 848 | break; |
JimCarver | 0:6b753f761943 | 849 | |
JimCarver | 0:6b753f761943 | 850 | case 3: |
JimCarver | 0:6b753f761943 | 851 | status_reg_setup[0] = 0x80; // Bit 7 of Status Reg 1 |
JimCarver | 0:6b753f761943 | 852 | status_reg_setup[1] = 0; |
JimCarver | 0:6b753f761943 | 853 | sr_write_size = 1; |
JimCarver | 0:6b753f761943 | 854 | sr_read_size = 1; |
JimCarver | 0:6b753f761943 | 855 | writeRegisterInst = 0x3E; |
JimCarver | 0:6b753f761943 | 856 | readRegisterInst = 0x3F; |
JimCarver | 0:6b753f761943 | 857 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 7 of Status Reg 1"); |
JimCarver | 0:6b753f761943 | 858 | break; |
JimCarver | 0:6b753f761943 | 859 | case 5: |
JimCarver | 0:6b753f761943 | 860 | status_reg_setup[0] = 0; |
JimCarver | 0:6b753f761943 | 861 | status_reg_setup[1] = 0x02; |
JimCarver | 0:6b753f761943 | 862 | readRegisterInst = 0x35; |
JimCarver | 0:6b753f761943 | 863 | sr_read_size = 1; |
JimCarver | 0:6b753f761943 | 864 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 1 of Status Reg 2 -special read command"); |
JimCarver | 0:6b753f761943 | 865 | break; |
JimCarver | 0:6b753f761943 | 866 | default: |
JimCarver | 0:6b753f761943 | 867 | QSPIF_LOG(QSPIF_DEBUG_WARNING, "WARNING: _setQuadEnable - Unsuported QER configuration"); |
JimCarver | 0:6b753f761943 | 868 | break; |
JimCarver | 0:6b753f761943 | 869 | |
JimCarver | 0:6b753f761943 | 870 | |
JimCarver | 0:6b753f761943 | 871 | } |
JimCarver | 0:6b753f761943 | 872 | |
JimCarver | 0:6b753f761943 | 873 | // Read Status Register |
JimCarver | 0:6b753f761943 | 874 | if (QSPI_STATUS_OK == _qspiSendGeneralCommand(readRegisterInst, -1, NULL, 0, (char *)status_reg, |
JimCarver | 0:6b753f761943 | 875 | sr_read_size) ) { // store received values in status_value |
JimCarver | 0:6b753f761943 | 876 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]); |
JimCarver | 0:6b753f761943 | 877 | } else { |
JimCarver | 0:6b753f761943 | 878 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed"); |
JimCarver | 0:6b753f761943 | 879 | return -1; |
JimCarver | 0:6b753f761943 | 880 | } |
JimCarver | 0:6b753f761943 | 881 | |
JimCarver | 0:6b753f761943 | 882 | // Set Bits for Quad Enable |
JimCarver | 0:6b753f761943 | 883 | status_reg[0] |= status_reg_setup[0]; |
JimCarver | 0:6b753f761943 | 884 | status_reg[1] |= status_reg_setup[1]; |
JimCarver | 0:6b753f761943 | 885 | |
JimCarver | 0:6b753f761943 | 886 | |
JimCarver | 0:6b753f761943 | 887 | // Write new Status Register Setup |
JimCarver | 0:6b753f761943 | 888 | if (_setWriteEnable() != 0) { |
JimCarver | 0:6b753f761943 | 889 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write Enabe failed\n"); |
JimCarver | 0:6b753f761943 | 890 | return -1; |
JimCarver | 0:6b753f761943 | 891 | } |
JimCarver | 0:6b753f761943 | 892 | |
JimCarver | 0:6b753f761943 | 893 | if ( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 894 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready, write failed"); |
JimCarver | 0:6b753f761943 | 895 | return -1; |
JimCarver | 0:6b753f761943 | 896 | } |
JimCarver | 0:6b753f761943 | 897 | |
JimCarver | 0:6b753f761943 | 898 | if (QSPI_STATUS_OK == _qspiSendGeneralCommand(writeRegisterInst, -1, (char *)status_reg, sr_write_size, NULL, |
JimCarver | 0:6b753f761943 | 899 | 0) ) { // Write QE to status_register |
JimCarver | 0:6b753f761943 | 900 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQuadEnable - Writing Status Register Success: value = 0x%x", |
JimCarver | 0:6b753f761943 | 901 | (int)status_reg[0]); |
JimCarver | 0:6b753f761943 | 902 | } else { |
JimCarver | 0:6b753f761943 | 903 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: _setQuadEnable - Writing Status Register failed"); |
JimCarver | 0:6b753f761943 | 904 | return -1; |
JimCarver | 0:6b753f761943 | 905 | } |
JimCarver | 0:6b753f761943 | 906 | |
JimCarver | 0:6b753f761943 | 907 | wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC); |
JimCarver | 0:6b753f761943 | 908 | |
JimCarver | 0:6b753f761943 | 909 | if ( false == _isMemReady()) { |
JimCarver | 0:6b753f761943 | 910 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready after write, failed"); |
JimCarver | 0:6b753f761943 | 911 | return -1; |
JimCarver | 0:6b753f761943 | 912 | } |
JimCarver | 0:6b753f761943 | 913 | |
JimCarver | 0:6b753f761943 | 914 | |
JimCarver | 0:6b753f761943 | 915 | // For Debug |
JimCarver | 0:6b753f761943 | 916 | memset(status_reg, 0, QSPI_MAX_STATUS_REGISTER_SIZE); |
JimCarver | 0:6b753f761943 | 917 | if (QSPI_STATUS_OK == _qspiSendGeneralCommand(readRegisterInst, -1, NULL, 0, (char *)status_reg, |
JimCarver | 0:6b753f761943 | 918 | sr_read_size) ) { // store received values in status_value |
JimCarver | 0:6b753f761943 | 919 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]); |
JimCarver | 0:6b753f761943 | 920 | } else { |
JimCarver | 0:6b753f761943 | 921 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed"); |
JimCarver | 0:6b753f761943 | 922 | return -1; |
JimCarver | 0:6b753f761943 | 923 | } |
JimCarver | 0:6b753f761943 | 924 | |
JimCarver | 0:6b753f761943 | 925 | |
JimCarver | 0:6b753f761943 | 926 | return 0;//((status_reg[0] & QSPI_STATUS_BIT_QE) != 0 ? 0 : -1); |
JimCarver | 0:6b753f761943 | 927 | } |
JimCarver | 0:6b753f761943 | 928 | |
JimCarver | 0:6b753f761943 | 929 | |
JimCarver | 0:6b753f761943 | 930 | int QSPIFBlockDevice::_sfdpDetectPageSize(uint8_t *basicParamTablePtr) |
JimCarver | 0:6b753f761943 | 931 | { |
JimCarver | 0:6b753f761943 | 932 | int page2PowerSize = ( (int)basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4; |
JimCarver | 0:6b753f761943 | 933 | int pageSize = _utilsMathPower(2, page2PowerSize); |
JimCarver | 0:6b753f761943 | 934 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _detectPageSize - Page Size: %d", pageSize); |
JimCarver | 0:6b753f761943 | 935 | return pageSize; |
JimCarver | 0:6b753f761943 | 936 | } |
JimCarver | 0:6b753f761943 | 937 | |
JimCarver | 0:6b753f761943 | 938 | |
JimCarver | 0:6b753f761943 | 939 | |
JimCarver | 0:6b753f761943 | 940 | int QSPIFBlockDevice::_sfdpDetectEraseTypesInstAndSize(uint8_t *basicParamTablePtr, unsigned int& erase4KInst, |
JimCarver | 0:6b753f761943 | 941 | unsigned int *eraseTypeInstArr, unsigned int *eraseTypeSizeArr) |
JimCarver | 0:6b753f761943 | 942 | { |
JimCarver | 0:6b753f761943 | 943 | erase4KInst = 0xff; |
JimCarver | 0:6b753f761943 | 944 | bool found4KEraseType = false; |
JimCarver | 0:6b753f761943 | 945 | uint8_t bitfield = 0x01; |
JimCarver | 0:6b753f761943 | 946 | |
JimCarver | 0:6b753f761943 | 947 | // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K |
JimCarver | 0:6b753f761943 | 948 | erase4KInst = basicParamTablePtr[QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE]; |
JimCarver | 0:6b753f761943 | 949 | |
JimCarver | 0:6b753f761943 | 950 | // Loop Erase Types 1-4 |
JimCarver | 0:6b753f761943 | 951 | for (int i_ind = 0; i_ind < 4; i_ind++) { |
JimCarver | 0:6b753f761943 | 952 | eraseTypeInstArr[i_ind] = 0xff; //0xFF default for unsupported type |
JimCarver | 0:6b753f761943 | 953 | eraseTypeSizeArr[i_ind] = _utilsMathPower(2, basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); |
JimCarver | 0:6b753f761943 | 954 | if (eraseTypeSizeArr[i_ind] > 1) { |
JimCarver | 0:6b753f761943 | 955 | // if size==1 type is not supported |
JimCarver | 0:6b753f761943 | 956 | eraseTypeInstArr[i_ind] = basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind]; |
JimCarver | 0:6b753f761943 | 957 | |
JimCarver | 0:6b753f761943 | 958 | if ((eraseTypeSizeArr[i_ind] < _minCommonEraseSize) || (_minCommonEraseSize == 0) ) { |
JimCarver | 0:6b753f761943 | 959 | //Set default minimal common erase for singal region |
JimCarver | 0:6b753f761943 | 960 | _minCommonEraseSize = eraseTypeSizeArr[i_ind]; |
JimCarver | 0:6b753f761943 | 961 | } |
JimCarver | 0:6b753f761943 | 962 | |
JimCarver | 0:6b753f761943 | 963 | if (eraseTypeSizeArr[i_ind] == 4096) { |
JimCarver | 0:6b753f761943 | 964 | found4KEraseType = true; |
JimCarver | 0:6b753f761943 | 965 | if (erase4KInst != eraseTypeInstArr[i_ind]) { |
JimCarver | 0:6b753f761943 | 966 | //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table |
JimCarver | 0:6b753f761943 | 967 | erase4KInst = eraseTypeInstArr[i_ind]; |
JimCarver | 0:6b753f761943 | 968 | QSPIF_LOG(QSPIF_DEBUG_WARNING, |
JimCarver | 0:6b753f761943 | 969 | "WARNING: _detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K"); |
JimCarver | 0:6b753f761943 | 970 | |
JimCarver | 0:6b753f761943 | 971 | } |
JimCarver | 0:6b753f761943 | 972 | } |
JimCarver | 0:6b753f761943 | 973 | _region_erase_types[0] |= bitfield; // If there's no region map, set region "0" types as defualt; |
JimCarver | 0:6b753f761943 | 974 | } |
JimCarver | 0:6b753f761943 | 975 | |
JimCarver | 0:6b753f761943 | 976 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), eraseTypeInstArr[i_ind], |
JimCarver | 0:6b753f761943 | 977 | eraseTypeSizeArr[i_ind]); |
JimCarver | 0:6b753f761943 | 978 | bitfield = bitfield << 1; |
JimCarver | 0:6b753f761943 | 979 | } |
JimCarver | 0:6b753f761943 | 980 | |
JimCarver | 0:6b753f761943 | 981 | if (false == found4KEraseType) { |
JimCarver | 0:6b753f761943 | 982 | QSPIF_LOG(QSPIF_DEBUG_WARNING, "WARNING: Couldn't find Erase Type for 4KB size"); |
JimCarver | 0:6b753f761943 | 983 | } |
JimCarver | 0:6b753f761943 | 984 | return 0; |
JimCarver | 0:6b753f761943 | 985 | } |
JimCarver | 0:6b753f761943 | 986 | |
JimCarver | 0:6b753f761943 | 987 | |
JimCarver | 0:6b753f761943 | 988 | int QSPIFBlockDevice::_sfdpDetectBestBusReadMode(uint8_t *basicParamTablePtr, bool& setQuadEnable, bool& isQPIMode, |
JimCarver | 0:6b753f761943 | 989 | unsigned int& readInst) |
JimCarver | 0:6b753f761943 | 990 | { |
JimCarver | 0:6b753f761943 | 991 | |
JimCarver | 0:6b753f761943 | 992 | bool isDone = false; |
JimCarver | 0:6b753f761943 | 993 | |
JimCarver | 0:6b753f761943 | 994 | setQuadEnable = false; |
JimCarver | 0:6b753f761943 | 995 | isQPIMode = false; |
JimCarver | 0:6b753f761943 | 996 | int dummyCycles = 0; |
JimCarver | 0:6b753f761943 | 997 | uint8_t examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE]; |
JimCarver | 0:6b753f761943 | 998 | |
JimCarver | 0:6b753f761943 | 999 | do { // compound statement is the loop body |
JimCarver | 0:6b753f761943 | 1000 | |
JimCarver | 0:6b753f761943 | 1001 | |
JimCarver | 0:6b753f761943 | 1002 | |
JimCarver | 0:6b753f761943 | 1003 | if (examinedByte & 0x10) { |
JimCarver | 0:6b753f761943 | 1004 | // QPI 4-4-4 Supported |
JimCarver | 0:6b753f761943 | 1005 | readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE]; |
JimCarver | 0:6b753f761943 | 1006 | setQuadEnable = true; |
JimCarver | 0:6b753f761943 | 1007 | isQPIMode = true; |
JimCarver | 0:6b753f761943 | 1008 | _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE - 1] >> 5) |
JimCarver | 0:6b753f761943 | 1009 | + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE - 1] & 0x1F); |
JimCarver | 0:6b753f761943 | 1010 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 4-4-4, Instruction: 0x%xh", _readInstruction); |
JimCarver | 0:6b753f761943 | 1011 | //_inst_width = QSPI_CFG_BUS_QUAD; |
JimCarver | 0:6b753f761943 | 1012 | _address_width = QSPI_CFG_BUS_QUAD; |
JimCarver | 0:6b753f761943 | 1013 | _data_width = QSPI_CFG_BUS_QUAD; |
JimCarver | 0:6b753f761943 | 1014 | |
JimCarver | 0:6b753f761943 | 1015 | break; |
JimCarver | 0:6b753f761943 | 1016 | } |
JimCarver | 0:6b753f761943 | 1017 | |
JimCarver | 0:6b753f761943 | 1018 | |
JimCarver | 0:6b753f761943 | 1019 | examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE]; |
JimCarver | 0:6b753f761943 | 1020 | if (examinedByte & 0x40) { |
JimCarver | 0:6b753f761943 | 1021 | // Fast Read 1-4-4 Supported |
JimCarver | 0:6b753f761943 | 1022 | readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE]; |
JimCarver | 0:6b753f761943 | 1023 | setQuadEnable = true; |
JimCarver | 0:6b753f761943 | 1024 | // dummy cycles + mode cycles = Dummy Cycles |
JimCarver | 0:6b753f761943 | 1025 | _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE - 1] >> 5) |
JimCarver | 0:6b753f761943 | 1026 | + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE - 1] & 0x1F); |
JimCarver | 0:6b753f761943 | 1027 | _address_width = QSPI_CFG_BUS_QUAD; |
JimCarver | 0:6b753f761943 | 1028 | _data_width = QSPI_CFG_BUS_QUAD; |
JimCarver | 0:6b753f761943 | 1029 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-4-4, Instruction: 0x%xh", _readInstruction); |
JimCarver | 0:6b753f761943 | 1030 | break; |
JimCarver | 0:6b753f761943 | 1031 | } |
JimCarver | 0:6b753f761943 | 1032 | if (examinedByte & 0x80) { |
JimCarver | 0:6b753f761943 | 1033 | // Fast Read 1-1-4 Supported |
JimCarver | 0:6b753f761943 | 1034 | readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE]; |
JimCarver | 0:6b753f761943 | 1035 | setQuadEnable = true; |
JimCarver | 0:6b753f761943 | 1036 | _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE - 1] >> 5) |
JimCarver | 0:6b753f761943 | 1037 | + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE - 1] & 0x1F); |
JimCarver | 0:6b753f761943 | 1038 | _data_width = QSPI_CFG_BUS_QUAD; |
JimCarver | 0:6b753f761943 | 1039 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-1-4, Instruction: 0x%xh", _readInstruction); |
JimCarver | 0:6b753f761943 | 1040 | break; |
JimCarver | 0:6b753f761943 | 1041 | } |
JimCarver | 0:6b753f761943 | 1042 | examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE]; |
JimCarver | 0:6b753f761943 | 1043 | if (examinedByte & 0x01) { |
JimCarver | 0:6b753f761943 | 1044 | // Fast Read 2-2-2 Supported |
JimCarver | 0:6b753f761943 | 1045 | readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE]; |
JimCarver | 0:6b753f761943 | 1046 | _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] >> 5) |
JimCarver | 0:6b753f761943 | 1047 | + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] & 0x1F); |
JimCarver | 0:6b753f761943 | 1048 | _address_width = QSPI_CFG_BUS_DUAL; |
JimCarver | 0:6b753f761943 | 1049 | _data_width = QSPI_CFG_BUS_DUAL; |
JimCarver | 0:6b753f761943 | 1050 | QSPIF_LOG(QSPIF_DEBUG_INFO, "/nINFO: Read Bus Mode set to 2-2-2, Instruction: 0x%xh", _readInstruction); |
JimCarver | 0:6b753f761943 | 1051 | break; |
JimCarver | 0:6b753f761943 | 1052 | } |
JimCarver | 0:6b753f761943 | 1053 | |
JimCarver | 0:6b753f761943 | 1054 | examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE]; |
JimCarver | 0:6b753f761943 | 1055 | if (examinedByte & 0x20) { |
JimCarver | 0:6b753f761943 | 1056 | // Fast Read 1-2-2 Supported |
JimCarver | 0:6b753f761943 | 1057 | readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE]; |
JimCarver | 0:6b753f761943 | 1058 | _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE - 1] >> 5) |
JimCarver | 0:6b753f761943 | 1059 | + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE - 1] & 0x1F); |
JimCarver | 0:6b753f761943 | 1060 | _address_width = QSPI_CFG_BUS_DUAL; |
JimCarver | 0:6b753f761943 | 1061 | _data_width = QSPI_CFG_BUS_DUAL; |
JimCarver | 0:6b753f761943 | 1062 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-2-2, Instruction: 0x%xh", _readInstruction); |
JimCarver | 0:6b753f761943 | 1063 | break; |
JimCarver | 0:6b753f761943 | 1064 | } |
JimCarver | 0:6b753f761943 | 1065 | if (examinedByte & 0x01) { |
JimCarver | 0:6b753f761943 | 1066 | // Fast Read 1-1-2 Supported |
JimCarver | 0:6b753f761943 | 1067 | readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE]; |
JimCarver | 0:6b753f761943 | 1068 | _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE - 1] >> 5) |
JimCarver | 0:6b753f761943 | 1069 | + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE - 1] & 0x1F); |
JimCarver | 0:6b753f761943 | 1070 | _data_width = QSPI_CFG_BUS_DUAL; |
JimCarver | 0:6b753f761943 | 1071 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-1-2, Instruction: 0x%xh", _readInstruction); |
JimCarver | 0:6b753f761943 | 1072 | break; |
JimCarver | 0:6b753f761943 | 1073 | } |
JimCarver | 0:6b753f761943 | 1074 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-1-1, Instruction: 0x%xh", _readInstruction); |
JimCarver | 0:6b753f761943 | 1075 | isDone = true; |
JimCarver | 0:6b753f761943 | 1076 | } while (isDone == false); |
JimCarver | 0:6b753f761943 | 1077 | |
JimCarver | 0:6b753f761943 | 1078 | return 0; |
JimCarver | 0:6b753f761943 | 1079 | } |
JimCarver | 0:6b753f761943 | 1080 | |
JimCarver | 0:6b753f761943 | 1081 | |
JimCarver | 0:6b753f761943 | 1082 | int QSPIFBlockDevice::_resetFlashMem() |
JimCarver | 0:6b753f761943 | 1083 | { |
JimCarver | 0:6b753f761943 | 1084 | int status = 0; |
JimCarver | 0:6b753f761943 | 1085 | char status_value[2] = {0}; |
JimCarver | 0:6b753f761943 | 1086 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "INFO: _resetFlashMem:\n"); |
JimCarver | 0:6b753f761943 | 1087 | //Read the Status Register from device |
JimCarver | 0:6b753f761943 | 1088 | if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RDSR, -1, NULL, 0, status_value, |
JimCarver | 0:6b753f761943 | 1089 | 1) ) { // store received values in status_value |
JimCarver | 0:6b753f761943 | 1090 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_value[0]); |
JimCarver | 0:6b753f761943 | 1091 | } else { |
JimCarver | 0:6b753f761943 | 1092 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed\n"); |
JimCarver | 0:6b753f761943 | 1093 | status = -1; |
JimCarver | 0:6b753f761943 | 1094 | } |
JimCarver | 0:6b753f761943 | 1095 | |
JimCarver | 0:6b753f761943 | 1096 | if (0 == status) { |
JimCarver | 0:6b753f761943 | 1097 | //Send Reset Enable |
JimCarver | 0:6b753f761943 | 1098 | if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RSTEN, -1, NULL, 0, NULL, |
JimCarver | 0:6b753f761943 | 1099 | 0) ) { // store received values in status_value |
JimCarver | 0:6b753f761943 | 1100 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Sending RSTEN Success\n"); |
JimCarver | 0:6b753f761943 | 1101 | } else { |
JimCarver | 0:6b753f761943 | 1102 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Sending RSTEN failed\n"); |
JimCarver | 0:6b753f761943 | 1103 | status = -1; |
JimCarver | 0:6b753f761943 | 1104 | } |
JimCarver | 0:6b753f761943 | 1105 | |
JimCarver | 0:6b753f761943 | 1106 | |
JimCarver | 0:6b753f761943 | 1107 | if (0 == status) { |
JimCarver | 0:6b753f761943 | 1108 | //Send Reset |
JimCarver | 0:6b753f761943 | 1109 | if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RST, -1, NULL, 0, NULL, |
JimCarver | 0:6b753f761943 | 1110 | 0)) { // store received values in status_value |
JimCarver | 0:6b753f761943 | 1111 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Sending RST Success\n"); |
JimCarver | 0:6b753f761943 | 1112 | } else { |
JimCarver | 0:6b753f761943 | 1113 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Sending RST failed\n"); |
JimCarver | 0:6b753f761943 | 1114 | status = -1; |
JimCarver | 0:6b753f761943 | 1115 | } |
JimCarver | 0:6b753f761943 | 1116 | |
JimCarver | 0:6b753f761943 | 1117 | _isMemReady(); |
JimCarver | 0:6b753f761943 | 1118 | } |
JimCarver | 0:6b753f761943 | 1119 | } |
JimCarver | 0:6b753f761943 | 1120 | |
JimCarver | 0:6b753f761943 | 1121 | return status; |
JimCarver | 0:6b753f761943 | 1122 | } |
JimCarver | 0:6b753f761943 | 1123 | |
JimCarver | 0:6b753f761943 | 1124 | |
JimCarver | 0:6b753f761943 | 1125 | bool QSPIFBlockDevice::_isMemReady() |
JimCarver | 0:6b753f761943 | 1126 | { |
JimCarver | 0:6b753f761943 | 1127 | char status_value[2]; |
JimCarver | 0:6b753f761943 | 1128 | int retries = 0; |
JimCarver | 0:6b753f761943 | 1129 | bool memReady = true; |
JimCarver | 0:6b753f761943 | 1130 | |
JimCarver | 0:6b753f761943 | 1131 | do { |
JimCarver | 0:6b753f761943 | 1132 | retries++; |
JimCarver | 0:6b753f761943 | 1133 | //Read the Status Register from device |
JimCarver | 0:6b753f761943 | 1134 | if (QSPI_STATUS_OK != _qspiSendGeneralCommand(QSPIF_RDSR, -1, NULL, 0, status_value, |
JimCarver | 0:6b753f761943 | 1135 | 2)) { // store received values in status_value |
JimCarver | 0:6b753f761943 | 1136 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed\n"); |
JimCarver | 0:6b753f761943 | 1137 | } |
JimCarver | 0:6b753f761943 | 1138 | } while ( (status_value[0] & 0x1) != 0 && retries < 10000 ); |
JimCarver | 0:6b753f761943 | 1139 | |
JimCarver | 0:6b753f761943 | 1140 | if ((status_value[0] & 0x1) != 0) { |
JimCarver | 0:6b753f761943 | 1141 | QSPIF_LOG(QSPIF_DEBUG_DEBUG, "ERROR: _isMemReady FALSE\n"); |
JimCarver | 0:6b753f761943 | 1142 | memReady = false; |
JimCarver | 0:6b753f761943 | 1143 | } |
JimCarver | 0:6b753f761943 | 1144 | return memReady; |
JimCarver | 0:6b753f761943 | 1145 | } |
JimCarver | 0:6b753f761943 | 1146 | |
JimCarver | 0:6b753f761943 | 1147 | |
JimCarver | 0:6b753f761943 | 1148 | int QSPIFBlockDevice::_setWriteEnable() |
JimCarver | 0:6b753f761943 | 1149 | { |
JimCarver | 0:6b753f761943 | 1150 | int status = 0; |
JimCarver | 0:6b753f761943 | 1151 | if (QSPI_STATUS_OK != _qspiSendGeneralCommand(QSPIF_WREN, -1, NULL, 0, NULL, 0)) { |
JimCarver | 0:6b753f761943 | 1152 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR:Sending WREN command FAILED\n"); |
JimCarver | 0:6b753f761943 | 1153 | status = -1; |
JimCarver | 0:6b753f761943 | 1154 | } |
JimCarver | 0:6b753f761943 | 1155 | return status; |
JimCarver | 0:6b753f761943 | 1156 | } |
JimCarver | 0:6b753f761943 | 1157 | |
JimCarver | 0:6b753f761943 | 1158 | |
JimCarver | 0:6b753f761943 | 1159 | |
JimCarver | 0:6b753f761943 | 1160 | /*********************************************/ |
JimCarver | 0:6b753f761943 | 1161 | /************* Utility Functions *************/ |
JimCarver | 0:6b753f761943 | 1162 | /*********************************************/ |
JimCarver | 0:6b753f761943 | 1163 | int QSPIFBlockDevice::_utilsMathPower(int base, int exp) |
JimCarver | 0:6b753f761943 | 1164 | { |
JimCarver | 0:6b753f761943 | 1165 | int result = 1; |
JimCarver | 0:6b753f761943 | 1166 | while (exp) { |
JimCarver | 0:6b753f761943 | 1167 | result *= base; |
JimCarver | 0:6b753f761943 | 1168 | exp--; |
JimCarver | 0:6b753f761943 | 1169 | } |
JimCarver | 0:6b753f761943 | 1170 | return result; |
JimCarver | 0:6b753f761943 | 1171 | } |
JimCarver | 0:6b753f761943 | 1172 | |
JimCarver | 0:6b753f761943 | 1173 | |
JimCarver | 0:6b753f761943 | 1174 | int QSPIFBlockDevice::_utilsFindAddrRegion(int offset) |
JimCarver | 0:6b753f761943 | 1175 | { |
JimCarver | 0:6b753f761943 | 1176 | if ((offset > (int)_deviceSizeBytes) || (_regions_count == 0)) { |
JimCarver | 0:6b753f761943 | 1177 | return -1; |
JimCarver | 0:6b753f761943 | 1178 | } |
JimCarver | 0:6b753f761943 | 1179 | |
JimCarver | 0:6b753f761943 | 1180 | if (_regions_count == 1) { |
JimCarver | 0:6b753f761943 | 1181 | return 0; |
JimCarver | 0:6b753f761943 | 1182 | } |
JimCarver | 0:6b753f761943 | 1183 | |
JimCarver | 0:6b753f761943 | 1184 | for (int i_ind = _regions_count - 2; i_ind >= 0; i_ind--) { |
JimCarver | 0:6b753f761943 | 1185 | |
JimCarver | 0:6b753f761943 | 1186 | if (offset > _region_high_boundary[i_ind]) { |
JimCarver | 0:6b753f761943 | 1187 | return (i_ind + 1); |
JimCarver | 0:6b753f761943 | 1188 | } |
JimCarver | 0:6b753f761943 | 1189 | } |
JimCarver | 0:6b753f761943 | 1190 | return -1; |
JimCarver | 0:6b753f761943 | 1191 | |
JimCarver | 0:6b753f761943 | 1192 | } |
JimCarver | 0:6b753f761943 | 1193 | |
JimCarver | 0:6b753f761943 | 1194 | |
JimCarver | 0:6b753f761943 | 1195 | int QSPIFBlockDevice::_utilsIterateNextLargestEraseType(uint8_t& bitfield, int size, int offset, int boundry) |
JimCarver | 0:6b753f761943 | 1196 | { |
JimCarver | 0:6b753f761943 | 1197 | uint8_t type_mask = 0x08; |
JimCarver | 0:6b753f761943 | 1198 | int i_ind = 0; |
JimCarver | 0:6b753f761943 | 1199 | int largestEraseType = 0; |
JimCarver | 0:6b753f761943 | 1200 | for (i_ind = 3; i_ind >= 0; i_ind--) { |
JimCarver | 0:6b753f761943 | 1201 | if (bitfield & type_mask) { |
JimCarver | 0:6b753f761943 | 1202 | largestEraseType = i_ind; |
JimCarver | 0:6b753f761943 | 1203 | if ( (size > _eraseTypeSizeArr[largestEraseType]) && |
JimCarver | 0:6b753f761943 | 1204 | ((boundry - offset) > _eraseTypeSizeArr[largestEraseType]) ) { |
JimCarver | 0:6b753f761943 | 1205 | break; |
JimCarver | 0:6b753f761943 | 1206 | } else { |
JimCarver | 0:6b753f761943 | 1207 | bitfield &= ~type_mask; |
JimCarver | 0:6b753f761943 | 1208 | } |
JimCarver | 0:6b753f761943 | 1209 | } |
JimCarver | 0:6b753f761943 | 1210 | type_mask = type_mask >> 1; |
JimCarver | 0:6b753f761943 | 1211 | } |
JimCarver | 0:6b753f761943 | 1212 | |
JimCarver | 0:6b753f761943 | 1213 | if (i_ind == 4) { |
JimCarver | 0:6b753f761943 | 1214 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: no erase type was found for current region addr"); |
JimCarver | 0:6b753f761943 | 1215 | } |
JimCarver | 0:6b753f761943 | 1216 | return largestEraseType; |
JimCarver | 0:6b753f761943 | 1217 | |
JimCarver | 0:6b753f761943 | 1218 | } |
JimCarver | 0:6b753f761943 | 1219 | |
JimCarver | 0:6b753f761943 | 1220 | |
JimCarver | 0:6b753f761943 | 1221 | /***************************************************/ |
JimCarver | 0:6b753f761943 | 1222 | /*********** QSPI Driver API Functions *************/ |
JimCarver | 0:6b753f761943 | 1223 | /***************************************************/ |
JimCarver | 0:6b753f761943 | 1224 | |
JimCarver | 0:6b753f761943 | 1225 | qspi_status_t QSPIFBlockDevice::_qspiSetFrequency(int freq) |
JimCarver | 0:6b753f761943 | 1226 | { |
JimCarver | 0:6b753f761943 | 1227 | return _qspi.set_frequency(freq); |
JimCarver | 0:6b753f761943 | 1228 | } |
JimCarver | 0:6b753f761943 | 1229 | |
JimCarver | 0:6b753f761943 | 1230 | |
JimCarver | 0:6b753f761943 | 1231 | qspi_status_t QSPIFBlockDevice::_qspiSendReadCommand(unsigned int readInst, void *buffer, bd_addr_t addr, |
JimCarver | 0:6b753f761943 | 1232 | bd_size_t size) |
JimCarver | 0:6b753f761943 | 1233 | { |
JimCarver | 0:6b753f761943 | 1234 | // Check the address and size fit onto the chip. |
JimCarver | 0:6b753f761943 | 1235 | |
JimCarver | 0:6b753f761943 | 1236 | /* OFR_DBG */ |
JimCarver | 0:6b753f761943 | 1237 | //MBED_ASSERT(is_valid_read(addr, size)); |
JimCarver | 0:6b753f761943 | 1238 | |
JimCarver | 0:6b753f761943 | 1239 | size_t bufLen = size; |
JimCarver | 0:6b753f761943 | 1240 | |
JimCarver | 0:6b753f761943 | 1241 | if (_qspi.read( readInst, -1, (unsigned int )addr, (char *)buffer, &bufLen) != QSPI_STATUS_OK ) { |
JimCarver | 0:6b753f761943 | 1242 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Read failed"); |
JimCarver | 0:6b753f761943 | 1243 | return QSPI_STATUS_ERROR; |
JimCarver | 0:6b753f761943 | 1244 | } |
JimCarver | 0:6b753f761943 | 1245 | |
JimCarver | 0:6b753f761943 | 1246 | return QSPI_STATUS_OK; |
JimCarver | 0:6b753f761943 | 1247 | |
JimCarver | 0:6b753f761943 | 1248 | } |
JimCarver | 0:6b753f761943 | 1249 | |
JimCarver | 0:6b753f761943 | 1250 | |
JimCarver | 0:6b753f761943 | 1251 | qspi_status_t QSPIFBlockDevice::_qspiSendProgramCommand(unsigned int progInst, const void *buffer, bd_addr_t addr, |
JimCarver | 0:6b753f761943 | 1252 | bd_size_t *size) |
JimCarver | 0:6b753f761943 | 1253 | { |
JimCarver | 0:6b753f761943 | 1254 | // Check the address and size fit onto the chip. |
JimCarver | 0:6b753f761943 | 1255 | //MBED_ASSERT(is_valid_program(addr, (*size))); |
JimCarver | 0:6b753f761943 | 1256 | qspi_status_t result = QSPI_STATUS_OK; |
JimCarver | 0:6b753f761943 | 1257 | |
JimCarver | 0:6b753f761943 | 1258 | result = _qspi.write( progInst, -1, addr/*(((unsigned int)addr) & 0x00FFFF00)*/, (char *)buffer, (size_t *)size); |
JimCarver | 0:6b753f761943 | 1259 | if (result != QSPI_STATUS_OK) { |
JimCarver | 0:6b753f761943 | 1260 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Write failed"); |
JimCarver | 0:6b753f761943 | 1261 | } |
JimCarver | 0:6b753f761943 | 1262 | |
JimCarver | 0:6b753f761943 | 1263 | return result; |
JimCarver | 0:6b753f761943 | 1264 | } |
JimCarver | 0:6b753f761943 | 1265 | |
JimCarver | 0:6b753f761943 | 1266 | |
JimCarver | 0:6b753f761943 | 1267 | qspi_status_t QSPIFBlockDevice::_qspiSendEraseCommand(unsigned int eraseInst, bd_addr_t addr, bd_size_t size) |
JimCarver | 0:6b753f761943 | 1268 | { |
JimCarver | 0:6b753f761943 | 1269 | // Check the address and size fit onto the chip. |
JimCarver | 0:6b753f761943 | 1270 | //MBED_ASSERT(is_valid_erase(addr, size)); |
JimCarver | 0:6b753f761943 | 1271 | |
JimCarver | 0:6b753f761943 | 1272 | qspi_status_t result = QSPI_STATUS_OK; |
JimCarver | 0:6b753f761943 | 1273 | |
JimCarver | 0:6b753f761943 | 1274 | result = _qspi.command_transfer(eraseInst, // command to send |
JimCarver | 0:6b753f761943 | 1275 | (((int)addr) & 0x00FFF000), // Align addr to 4096 |
JimCarver | 0:6b753f761943 | 1276 | NULL, // do not transmit |
JimCarver | 0:6b753f761943 | 1277 | 0, // do not transmit |
JimCarver | 0:6b753f761943 | 1278 | NULL, // just receive two bytes of data |
JimCarver | 0:6b753f761943 | 1279 | 0); // store received values in status_value |
JimCarver | 0:6b753f761943 | 1280 | if (QSPI_STATUS_OK != result) { |
JimCarver | 0:6b753f761943 | 1281 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase failed"); |
JimCarver | 0:6b753f761943 | 1282 | } |
JimCarver | 0:6b753f761943 | 1283 | |
JimCarver | 0:6b753f761943 | 1284 | return result; |
JimCarver | 0:6b753f761943 | 1285 | |
JimCarver | 0:6b753f761943 | 1286 | } |
JimCarver | 0:6b753f761943 | 1287 | |
JimCarver | 0:6b753f761943 | 1288 | |
JimCarver | 0:6b753f761943 | 1289 | qspi_status_t QSPIFBlockDevice::_qspiSendGeneralCommand(unsigned int instruction, bd_addr_t addr, const char *tx_buffer, |
JimCarver | 0:6b753f761943 | 1290 | size_t tx_length, const char *rx_buffer, size_t rx_length) |
JimCarver | 0:6b753f761943 | 1291 | { |
JimCarver | 0:6b753f761943 | 1292 | |
JimCarver | 0:6b753f761943 | 1293 | |
JimCarver | 0:6b753f761943 | 1294 | qspi_status_t status = _qspi.command_transfer(instruction, (int)addr, tx_buffer, tx_length, rx_buffer, rx_length); |
JimCarver | 0:6b753f761943 | 1295 | |
JimCarver | 0:6b753f761943 | 1296 | if (QSPI_STATUS_OK != status) { |
JimCarver | 0:6b753f761943 | 1297 | QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR:Sending Generic command: %x", instruction); |
JimCarver | 0:6b753f761943 | 1298 | } |
JimCarver | 0:6b753f761943 | 1299 | |
JimCarver | 0:6b753f761943 | 1300 | return status; |
JimCarver | 0:6b753f761943 | 1301 | } |
JimCarver | 0:6b753f761943 | 1302 | |
JimCarver | 0:6b753f761943 | 1303 | |
JimCarver | 0:6b753f761943 | 1304 | qspi_status_t QSPIFBlockDevice::_qspiConfiureFormat(qspi_bus_width_t inst_width, qspi_bus_width_t address_width, |
JimCarver | 0:6b753f761943 | 1305 | qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width, |
JimCarver | 0:6b753f761943 | 1306 | int dummy_cycles) |
JimCarver | 0:6b753f761943 | 1307 | { |
JimCarver | 0:6b753f761943 | 1308 | _qspi.configure_format( inst_width, address_width, address_size, alt_width, alt_size, data_width, dummy_cycles); |
JimCarver | 0:6b753f761943 | 1309 | |
JimCarver | 0:6b753f761943 | 1310 | return QSPI_STATUS_OK; |
JimCarver | 0:6b753f761943 | 1311 | } |
JimCarver | 0:6b753f761943 | 1312 | |
JimCarver | 0:6b753f761943 | 1313 | |
JimCarver | 0:6b753f761943 | 1314 | |
JimCarver | 0:6b753f761943 | 1315 | |
JimCarver | 0:6b753f761943 | 1316 |