Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
DataFlashBlockDevice.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2016 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 "DataFlashBlockDevice.h" 00018 #include "mbed_atomic.h" 00019 #include "rtos/ThisThread.h" 00020 #include <inttypes.h> 00021 00022 using namespace mbed; 00023 00024 /* constants */ 00025 #define DATAFLASH_READ_SIZE 1 00026 #define DATAFLASH_PROG_SIZE 1 00027 #define DATAFLASH_TIMEOUT 10000 00028 #define DATAFLASH_ID_MATCH 0x1F20 00029 #define DATAFLASH_ID_DENSITY_MASK 0x001F 00030 #define DATAFLASH_PAGE_SIZE_256 0x0100 00031 #define DATAFLASH_PAGE_SIZE_264 0x0108 00032 #define DATAFLASH_PAGE_SIZE_512 0x0200 00033 #define DATAFLASH_PAGE_SIZE_528 0x0210 00034 #define DATAFLASH_BLOCK_SIZE_2K 0x0800 00035 #define DATAFLASH_BLOCK_SIZE_2K1 0x0840 00036 #define DATAFLASH_BLOCK_SIZE_4K 0x1000 00037 #define DATAFLASH_BLOCK_SIZE_4K1 0x1080 00038 #define DATAFLASH_PAGE_BIT_264 9 00039 #define DATAFLASH_PAGE_BIT_528 10 00040 00041 /* enable debug */ 00042 #ifndef DATAFLASH_DEBUG 00043 #define DATAFLASH_DEBUG 0 00044 #endif /* DATAFLASH_DEBUG */ 00045 00046 #if DATAFLASH_DEBUG 00047 #define DEBUG_PRINTF(...) printf(__VA_ARGS__) 00048 #else 00049 #define DEBUG_PRINTF(...) 00050 #endif 00051 00052 void _print_status(uint16_t status); 00053 00054 /* non-exhaustive opcode list */ 00055 enum opcode { 00056 DATAFLASH_OP_NOP = 0x00, 00057 DATAFLASH_OP_STATUS = 0xD7, 00058 DATAFLASH_OP_ID = 0x9F, 00059 DATAFLASH_OP_READ_LOW_POWER = 0x01, 00060 DATAFLASH_OP_READ_LOW_FREQUENCY = 0x03, 00061 DATAFLASH_OP_PROGRAM_DIRECT = 0x02, // Program through Buffer 1 without Built-In Erase 00062 DATAFLASH_OP_PROGRAM_DIRECT_WITH_ERASE = 0x82, 00063 DATAFLASH_OP_ERASE_BLOCK = 0x50, 00064 DATAFLASH_OP_ERASE_PAGE = 0x81, 00065 }; 00066 00067 /* non-exhaustive command list */ 00068 enum command { 00069 DATAFLASH_COMMAND_WRITE_DISABLE = 0x3D2A7FA9, 00070 DATAFLASH_COMMAND_WRITE_ENABLE = 0x3D2A7F9A, 00071 DATAFLASH_COMMAND_BINARY_PAGE_SIZE = 0x3D2A80A6, 00072 DATAFLASH_COMMAND_DATAFLASH_PAGE_SIZE = 0x3D2A80A7, 00073 }; 00074 00075 /* bit masks for interpreting the status register */ 00076 enum status_bit { 00077 DATAFLASH_BIT_READY = (0x01 << 15), 00078 DATAFLASH_BIT_COMPARE = (0x01 << 14), 00079 DATAFLASH_BIT_DENSITY = (0x0F << 10), 00080 DATAFLASH_BIT_PROTECT = (0x01 << 9), 00081 DATAFLASH_BIT_PAGE_SIZE = (0x01 << 8), 00082 00083 DATAFLASH_BIT_ERASE_PROGRAM_ERROR = (0x01 << 5), 00084 DATAFLASH_BIT_SECTOR_LOCKDOWN = (0x01 << 3), 00085 DATAFLASH_BIT_PROGRAM_SUSPEND_2 = (0x01 << 2), 00086 DATAFLASH_BIT_PROGRAM_SUSPEND_1 = (0x01 << 1), 00087 DATAFLASH_BIT_ERASE_SUSPEND = (0x01 << 0), 00088 }; 00089 00090 /* bit masks for detecting density from status register */ 00091 enum status_density { 00092 DATAFLASH_STATUS_DENSITY_2_MBIT = (0x05 << 10), 00093 DATAFLASH_STATUS_DENSITY_4_MBIT = (0x07 << 10), 00094 DATAFLASH_STATUS_DENSITY_8_MBIT = (0x09 << 10), 00095 DATAFLASH_STATUS_DENSITY_16_MBIT = (0x0B << 10), 00096 DATAFLASH_STATUS_DENSITY_32_MBIT = (0x0D << 10), 00097 DATAFLASH_STATUS_DENSITY_64_MBIT = (0x0F << 10), 00098 }; 00099 00100 /* code for calculating density */ 00101 enum id_density { 00102 DATAFLASH_ID_DENSITY_2_MBIT = 0x03, 00103 DATAFLASH_ID_DENSITY_4_MBIT = 0x04, 00104 DATAFLASH_ID_DENSITY_8_MBIT = 0x05, 00105 DATAFLASH_ID_DENSITY_16_MBIT = 0x06, 00106 DATAFLASH_ID_DENSITY_32_MBIT = 0x07, 00107 DATAFLASH_ID_DENSITY_64_MBIT = 0x08, 00108 }; 00109 00110 /* typical duration in milliseconds for each operation */ 00111 enum timing { 00112 DATAFLASH_TIMING_ERASE_PROGRAM_PAGE = 17, 00113 DATAFLASH_TIMING_PROGRAM_PAGE = 3, 00114 DATAFLASH_TIMING_ERASE_PAGE = 12, 00115 DATAFLASH_TIMING_ERASE_BLOCK = 45, 00116 DATAFLASH_TIMING_ERASE_SECTOR = 700, 00117 DATAFLASH_TIMING_ERASE_CHIP = 45000 00118 }; 00119 00120 /* frequency domains */ 00121 enum frequency { 00122 DATAFLASH_LOW_POWER_FREQUENCY = 15000000, 00123 DATAFLASH_LOW_FREQUENCY = 50000000, 00124 DATAFLASH_HIGH_FREQUENCY = 85000000, 00125 DATAFLASH_HIGHEST_FREQUENCY = 104000000 00126 }; 00127 00128 /* number of dummy bytes required in each frequency domain */ 00129 enum dummy { 00130 DATAFLASH_LOW_POWER_BYTES = 0, 00131 DATAFLASH_LOW_FREQUENCY_BYTES = 0, 00132 DATAFLASH_HIGH_FREQUENCY_BYTES = 1, 00133 DATAFLASH_HIGHEST_FREQUENCY_BYTES = 2 00134 }; 00135 00136 DataFlashBlockDevice::DataFlashBlockDevice(PinName mosi, 00137 PinName miso, 00138 PinName sclk, 00139 PinName cs, 00140 int freq, 00141 PinName nwp) 00142 : _spi(mosi, miso, sclk), 00143 _cs(cs, 1), 00144 _nwp(nwp), 00145 _device_size(0), 00146 _page_size(0), 00147 _block_size(0), 00148 _is_initialized(0), 00149 _init_ref_count(0) 00150 { 00151 /* check that frequency is within range */ 00152 if (freq > DATAFLASH_LOW_FREQUENCY) { 00153 00154 /* cap frequency at the highest supported one */ 00155 _spi.frequency(DATAFLASH_LOW_FREQUENCY); 00156 00157 } else { 00158 /* freqency is valid, use as-is */ 00159 _spi.frequency(freq); 00160 } 00161 00162 /* write protect chip if pin is connected */ 00163 if (nwp != NC) { 00164 _nwp = 0; 00165 } 00166 } 00167 00168 int DataFlashBlockDevice::init() 00169 { 00170 _mutex.lock(); 00171 DEBUG_PRINTF("init\r\n"); 00172 00173 if (!_is_initialized) { 00174 _init_ref_count = 0; 00175 } 00176 00177 uint32_t val = core_util_atomic_incr_u32 (&_init_ref_count, 1); 00178 00179 if (val != 1) { 00180 _mutex.unlock(); 00181 return BD_ERROR_OK; 00182 } 00183 00184 int result = BD_ERROR_DEVICE_ERROR; 00185 00186 /* read ID register to validate model and set dimensions */ 00187 uint16_t id = _get_register(DATAFLASH_OP_ID); 00188 00189 DEBUG_PRINTF("id: %04X\r\n", id & DATAFLASH_ID_MATCH); 00190 00191 /* get status register to verify the page size mode */ 00192 uint16_t status = _get_register(DATAFLASH_OP_STATUS); 00193 00194 /* manufacture ID match */ 00195 if ((id & DATAFLASH_ID_MATCH) == DATAFLASH_ID_MATCH) { 00196 00197 /* calculate density */ 00198 _device_size = 0x8000 << (id & DATAFLASH_ID_DENSITY_MASK); 00199 00200 bool binary_page_size = true; 00201 00202 /* check if device is configured for binary page sizes */ 00203 if ((status & DATAFLASH_BIT_PAGE_SIZE) == DATAFLASH_BIT_PAGE_SIZE) { 00204 DEBUG_PRINTF("Page size is binary\r\n"); 00205 00206 #if MBED_CONF_DATAFLASH_DATAFLASH_SIZE 00207 /* send reconfiguration command */ 00208 _write_command(DATAFLASH_COMMAND_DATAFLASH_PAGE_SIZE, NULL, 0); 00209 00210 /* wait for device to be ready and update return code */ 00211 result = _sync(); 00212 00213 /* set binary flag */ 00214 binary_page_size = false; 00215 #else 00216 /* set binary flag */ 00217 binary_page_size = true; 00218 #endif 00219 } else { 00220 DEBUG_PRINTF("Page size is not binary\r\n"); 00221 00222 #if MBED_CONF_DATAFLASH_BINARY_SIZE 00223 /* send reconfiguration command */ 00224 _write_command(DATAFLASH_COMMAND_BINARY_PAGE_SIZE, NULL, 0); 00225 00226 /* wait for device to be ready and update return code */ 00227 result = _sync(); 00228 00229 /* set binary flag */ 00230 binary_page_size = true; 00231 #else 00232 /* set binary flag */ 00233 binary_page_size = false; 00234 #endif 00235 } 00236 00237 /* set page program size and block erase size */ 00238 switch (id & DATAFLASH_ID_DENSITY_MASK) { 00239 case DATAFLASH_ID_DENSITY_2_MBIT: 00240 case DATAFLASH_ID_DENSITY_4_MBIT: 00241 case DATAFLASH_ID_DENSITY_8_MBIT: 00242 case DATAFLASH_ID_DENSITY_64_MBIT: 00243 if (binary_page_size) { 00244 _page_size = DATAFLASH_PAGE_SIZE_256; 00245 _block_size = DATAFLASH_BLOCK_SIZE_2K; 00246 } else { 00247 _page_size = DATAFLASH_PAGE_SIZE_264; 00248 _block_size = DATAFLASH_BLOCK_SIZE_2K1; 00249 00250 /* adjust device size */ 00251 _device_size = (_device_size / DATAFLASH_PAGE_SIZE_256) * 00252 DATAFLASH_PAGE_SIZE_264; 00253 } 00254 break; 00255 case DATAFLASH_ID_DENSITY_16_MBIT: 00256 case DATAFLASH_ID_DENSITY_32_MBIT: 00257 if (binary_page_size) { 00258 _page_size = DATAFLASH_PAGE_SIZE_512; 00259 _block_size = DATAFLASH_BLOCK_SIZE_4K; 00260 } else { 00261 _page_size = DATAFLASH_PAGE_SIZE_528; 00262 _block_size = DATAFLASH_BLOCK_SIZE_4K1; 00263 00264 /* adjust device size */ 00265 _device_size = (_device_size / DATAFLASH_PAGE_SIZE_512) * 00266 DATAFLASH_PAGE_SIZE_528; 00267 } 00268 break; 00269 default: 00270 break; 00271 } 00272 00273 DEBUG_PRINTF("density: %" PRIu16 "\r\n", id & DATAFLASH_ID_DENSITY_MASK); 00274 DEBUG_PRINTF("size: %" PRIu32 "\r\n", _device_size); 00275 DEBUG_PRINTF("page: %" PRIu16 "\r\n", _page_size); 00276 DEBUG_PRINTF("block: %" PRIu16 "\r\n", _block_size); 00277 00278 /* device successfully detected, set OK error code */ 00279 result = BD_ERROR_OK; 00280 } 00281 00282 /* write protect device when idle */ 00283 _write_enable(false); 00284 00285 if (result == BD_ERROR_OK) { 00286 _is_initialized = true; 00287 } 00288 00289 _mutex.unlock(); 00290 return result; 00291 } 00292 00293 int DataFlashBlockDevice::deinit() 00294 { 00295 _mutex.lock(); 00296 DEBUG_PRINTF("deinit\r\n"); 00297 00298 if (!_is_initialized) { 00299 _init_ref_count = 0; 00300 _mutex.unlock(); 00301 return BD_ERROR_OK; 00302 } 00303 00304 uint32_t val = core_util_atomic_decr_u32 (&_init_ref_count, 1); 00305 00306 if (val) { 00307 _mutex.unlock(); 00308 return BD_ERROR_OK; 00309 } 00310 00311 _is_initialized = false; 00312 _mutex.unlock(); 00313 return BD_ERROR_OK; 00314 } 00315 00316 int DataFlashBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) 00317 { 00318 _mutex.lock(); 00319 DEBUG_PRINTF("read: %p %" PRIX64 " %" PRIX64 "\r\n", buffer, addr, size); 00320 00321 if (!_is_initialized) { 00322 _mutex.unlock(); 00323 return BD_ERROR_DEVICE_ERROR; 00324 } 00325 00326 int result = BD_ERROR_DEVICE_ERROR; 00327 00328 /* check parameters are valid and the read is within bounds */ 00329 if (is_valid_read(addr, size) && buffer) { 00330 00331 uint8_t *external_buffer = static_cast<uint8_t *>(buffer); 00332 00333 /* activate device */ 00334 _cs = 0; 00335 00336 /* send read opcode */ 00337 _spi.write(DATAFLASH_OP_READ_LOW_FREQUENCY); 00338 00339 /* translate address */ 00340 uint32_t address = _translate_address(addr); 00341 00342 DEBUG_PRINTF("address: %" PRIX32 "\r\n", address); 00343 00344 /* send read address */ 00345 _spi.write((address >> 16) & 0xFF); 00346 _spi.write((address >> 8) & 0xFF); 00347 _spi.write(address & 0xFF); 00348 00349 /* clock out one byte at a time and store in external buffer */ 00350 for (uint32_t index = 0; index < size; index++) { 00351 external_buffer[index] = _spi.write(DATAFLASH_OP_NOP); 00352 } 00353 00354 /* deactivate device */ 00355 _cs = 1; 00356 00357 result = BD_ERROR_OK; 00358 } 00359 00360 _mutex.unlock(); 00361 return result; 00362 } 00363 00364 int DataFlashBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) 00365 { 00366 _mutex.lock(); 00367 DEBUG_PRINTF("program: %p %" PRIX64 " %" PRIX64 "\r\n", buffer, addr, size); 00368 00369 if (!_is_initialized) { 00370 _mutex.unlock(); 00371 return BD_ERROR_DEVICE_ERROR; 00372 } 00373 00374 int result = BD_ERROR_DEVICE_ERROR; 00375 00376 /* check parameters are valid and the write is within bounds */ 00377 if (is_valid_program(addr, size) && buffer) { 00378 00379 const uint8_t *external_buffer = static_cast<const uint8_t *>(buffer); 00380 00381 /* Each write command can only cover one page at a time. 00382 Find page and current page offset for handling unaligned writes. 00383 */ 00384 uint32_t page_number = addr / _page_size; 00385 uint32_t page_offset = addr % _page_size; 00386 00387 /* disable write protection */ 00388 _write_enable(true); 00389 00390 /* continue until all bytes have been written */ 00391 uint32_t bytes_written = 0; 00392 while (bytes_written < size) { 00393 00394 /* find remaining bytes to be written */ 00395 uint32_t bytes_remaining = size - bytes_written; 00396 00397 /* cap the value at the page size and offset */ 00398 if (bytes_remaining > (_page_size - page_offset)) { 00399 bytes_remaining = _page_size - page_offset; 00400 } 00401 00402 /* Write one page, bytes_written keeps track of the progress, 00403 page_number is the page address, and page_offset is non-zero for 00404 unaligned writes. 00405 */ 00406 result = _write_page(&external_buffer[bytes_written], 00407 page_number, 00408 page_offset, 00409 bytes_remaining); 00410 00411 /* update loop variables upon success otherwise break loop */ 00412 if (result == BD_ERROR_OK) { 00413 bytes_written += bytes_remaining; 00414 page_number++; 00415 00416 /* After the first successful write, 00417 all subsequent writes will be aligned. 00418 */ 00419 page_offset = 0; 00420 } else { 00421 break; 00422 } 00423 } 00424 00425 /* enable write protection */ 00426 _write_enable(false); 00427 } 00428 00429 _mutex.unlock(); 00430 return result; 00431 } 00432 00433 int DataFlashBlockDevice::erase(bd_addr_t addr, bd_size_t size) 00434 { 00435 _mutex.lock(); 00436 DEBUG_PRINTF("erase: %" PRIX64 " %" PRIX64 "\r\n", addr, size); 00437 00438 if (!_is_initialized) { 00439 _mutex.unlock(); 00440 return BD_ERROR_DEVICE_ERROR; 00441 } 00442 00443 int result = BD_ERROR_DEVICE_ERROR; 00444 00445 /* check parameters are valid and the erase is within bounds */ 00446 if (is_valid_erase(addr, size)) { 00447 00448 /* disable write protection */ 00449 _write_enable(true); 00450 00451 /* erase one page at a time until the full size has been erased */ 00452 uint32_t erased = 0; 00453 while (erased < size) { 00454 00455 /* set page erase opcode */ 00456 uint32_t command = DATAFLASH_OP_ERASE_PAGE; 00457 00458 /* translate address */ 00459 uint32_t address = _translate_address(addr); 00460 00461 /* set page address */ 00462 command = (command << 8) | ((address >> 16) & 0xFF); 00463 command = (command << 8) | ((address >> 8) & 0xFF); 00464 command = (command << 8) | (address & 0xFF); 00465 00466 /* send command to device */ 00467 _write_command(command, NULL, 0); 00468 00469 /* wait until device is ready and update return value */ 00470 result = _sync(); 00471 00472 /* if erase failed, break loop */ 00473 if (result != BD_ERROR_OK) { 00474 break; 00475 } 00476 00477 /* update loop variables */ 00478 addr += _page_size; 00479 erased += _page_size; 00480 } 00481 00482 /* enable write protection */ 00483 _write_enable(false); 00484 } 00485 00486 _mutex.unlock(); 00487 return result; 00488 } 00489 00490 bd_size_t DataFlashBlockDevice::get_read_size() const 00491 { 00492 DEBUG_PRINTF("read size: %d\r\n", DATAFLASH_READ_SIZE); 00493 00494 return DATAFLASH_READ_SIZE; 00495 } 00496 00497 bd_size_t DataFlashBlockDevice::get_program_size() const 00498 { 00499 DEBUG_PRINTF("program size: %d\r\n", DATAFLASH_PROG_SIZE); 00500 00501 return DATAFLASH_PROG_SIZE; 00502 } 00503 00504 bd_size_t DataFlashBlockDevice::get_erase_size() const 00505 { 00506 _mutex.lock(); 00507 DEBUG_PRINTF("erase size: %" PRIX16 "\r\n", _page_size); 00508 bd_size_t block_size = _page_size; 00509 _mutex.unlock(); 00510 return block_size; 00511 } 00512 00513 bd_size_t DataFlashBlockDevice::get_erase_size(bd_addr_t addr) const 00514 { 00515 _mutex.lock(); 00516 DEBUG_PRINTF("erase size: %" PRIX16 "\r\n", _page_size); 00517 bd_size_t block_size = _page_size; 00518 _mutex.unlock(); 00519 return block_size; 00520 } 00521 00522 bd_size_t DataFlashBlockDevice::size() const 00523 { 00524 _mutex.lock(); 00525 DEBUG_PRINTF("device size: %" PRIX32 "\r\n", _device_size); 00526 bd_size_t device_size = _device_size; 00527 _mutex.unlock(); 00528 return device_size; 00529 } 00530 00531 const char *DataFlashBlockDevice::get_type() const 00532 { 00533 return "DATAFLASH"; 00534 } 00535 00536 /** 00537 * @brief Function for reading a specific register. 00538 * @details Used for reading either the Status Register or Manufacture and ID Register. 00539 * 00540 * @param opcode Register to be read. 00541 * @return value. 00542 */ 00543 uint16_t DataFlashBlockDevice::_get_register(uint8_t opcode) 00544 { 00545 _mutex.lock(); 00546 DEBUG_PRINTF("_get_register: %" PRIX8 "\r\n", opcode); 00547 00548 /* activate device */ 00549 _cs = 0; 00550 00551 /* write opcode */ 00552 _spi.write(opcode); 00553 00554 /* read and store result */ 00555 int status = (_spi.write(DATAFLASH_OP_NOP)); 00556 status = (status << 8) | (_spi.write(DATAFLASH_OP_NOP)); 00557 00558 /* deactivate device */ 00559 _cs = 1; 00560 00561 _mutex.unlock(); 00562 return status; 00563 } 00564 00565 /** 00566 * @brief Function for sending command and data to device. 00567 * @details The command can be an opcode with address and data or 00568 * a 4 byte command without data. 00569 * 00570 * The supported frequencies and the opcode used do not 00571 * require dummy bytes to be sent after command. 00572 * 00573 * @param command Opcode with address or 4 byte command. 00574 * @param buffer Data to be sent after command. 00575 * @param size Size of buffer. 00576 */ 00577 void DataFlashBlockDevice::_write_command(uint32_t command, const uint8_t *buffer, uint32_t size) 00578 { 00579 DEBUG_PRINTF("_write_command: %" PRIX32 " %p %" PRIX32 "\r\n", command, buffer, size); 00580 00581 /* activate device */ 00582 _cs = 0; 00583 00584 /* send command (opcode with data or 4 byte command) */ 00585 _spi.write((command >> 24) & 0xFF); 00586 _spi.write((command >> 16) & 0xFF); 00587 _spi.write((command >> 8) & 0xFF); 00588 _spi.write(command & 0xFF); 00589 00590 /* send optional data */ 00591 if (buffer && size) { 00592 for (uint32_t index = 0; index < size; index++) { 00593 _spi.write(buffer[index]); 00594 } 00595 } 00596 00597 /* deactivate device */ 00598 _cs = 1; 00599 } 00600 00601 /** 00602 * @brief Enable and disable write protection. 00603 * 00604 * @param enable Boolean for enabling or disabling write protection. 00605 */ 00606 void DataFlashBlockDevice::_write_enable(bool enable) 00607 { 00608 DEBUG_PRINTF("_write_enable: %d\r\n", enable); 00609 00610 /* enable writing, disable write protection */ 00611 if (enable) { 00612 /* if not-write-protected pin is connected, select it */ 00613 if (_nwp.is_connected()) { 00614 _nwp = 1; 00615 } 00616 00617 /* send 4 byte command enabling writes */ 00618 _write_command(DATAFLASH_COMMAND_WRITE_ENABLE, NULL, 0); 00619 } else { 00620 00621 /* if not-write-protected pin is connected, deselect it */ 00622 if (_nwp.is_connected()) { 00623 _nwp = 0; 00624 } 00625 00626 /* send 4 byte command disabling writes */ 00627 _write_command(DATAFLASH_COMMAND_WRITE_DISABLE, NULL, 0); 00628 } 00629 } 00630 00631 /** 00632 * @brief Sleep and poll status register until device is ready for next command. 00633 * 00634 * @return BlockDevice compatible error code. 00635 */ 00636 int DataFlashBlockDevice::_sync(void) 00637 { 00638 DEBUG_PRINTF("_sync\r\n"); 00639 00640 /* default return value if operation times out */ 00641 int result = BD_ERROR_DEVICE_ERROR; 00642 00643 /* Poll device until a hard coded timeout is reached. 00644 The polling interval is based on the typical page program time. 00645 */ 00646 for (uint32_t timeout = 0; 00647 timeout < DATAFLASH_TIMEOUT; 00648 timeout += DATAFLASH_TIMING_ERASE_PROGRAM_PAGE) { 00649 00650 /* get status register */ 00651 uint16_t status = _get_register(DATAFLASH_OP_STATUS); 00652 00653 /* erase/program bit set, exit with error code set */ 00654 if (status & DATAFLASH_BIT_ERASE_PROGRAM_ERROR) { 00655 DEBUG_PRINTF("DATAFLASH_BIT_ERASE_PROGRAM_ERROR\r\n"); 00656 break; 00657 /* device ready, set OK code set */ 00658 } else if (status & DATAFLASH_BIT_READY) { 00659 DEBUG_PRINTF("DATAFLASH_BIT_READY\r\n"); 00660 result = BD_ERROR_OK; 00661 break; 00662 /* wait the typical write period before trying again */ 00663 } else { 00664 DEBUG_PRINTF("sleep_for: %d\r\n", DATAFLASH_TIMING_ERASE_PROGRAM_PAGE); 00665 rtos::ThisThread::sleep_for(DATAFLASH_TIMING_ERASE_PROGRAM_PAGE); 00666 } 00667 } 00668 00669 return result; 00670 } 00671 00672 /** 00673 * @brief Write single page. 00674 * @details Address can be unaligned. 00675 * 00676 * @param buffer Data to write. 00677 * @param addr Address to write from. 00678 * @param size Bytes to write. Can at most be the full page. 00679 * @return BlockDevice error code. 00680 */ 00681 int DataFlashBlockDevice::_write_page(const uint8_t *buffer, 00682 uint32_t page, 00683 uint32_t offset, 00684 uint32_t size) 00685 { 00686 DEBUG_PRINTF("_write_page: %p %" PRIX32 " %" PRIX32 "\r\n", buffer, page, size); 00687 00688 uint32_t command = DATAFLASH_OP_NOP; 00689 00690 /* opcode for writing directly to device, in a single command, 00691 assuming the page has been erased before hand. 00692 */ 00693 command = DATAFLASH_OP_PROGRAM_DIRECT; 00694 00695 uint32_t address = 0; 00696 00697 /* convert page number and offset into device address based on address format */ 00698 if (_page_size == DATAFLASH_PAGE_SIZE_264) { 00699 address = (page << DATAFLASH_PAGE_BIT_264) | offset; 00700 } else if (_page_size == DATAFLASH_PAGE_SIZE_528) { 00701 address = (page << DATAFLASH_PAGE_BIT_528) | offset; 00702 } else { 00703 address = (page * _page_size) | offset; 00704 } 00705 00706 /* set write address */ 00707 command = (command << 8) | ((address >> 16) & 0xFF); 00708 command = (command << 8) | ((address >> 8) & 0xFF); 00709 command = (command << 8) | (address & 0xFF); 00710 00711 /* send write command with data */ 00712 _write_command(command, buffer, size); 00713 00714 /* wait until device is ready before continuing */ 00715 int result = _sync(); 00716 00717 return result; 00718 } 00719 00720 /** 00721 * @brief Translate address. 00722 * @details If the device is configured for non-binary page sizes, 00723 * the address is translated from binary to non-binary form. 00724 * 00725 * @param addr Binary address. 00726 * @return Address in format expected by device. 00727 */ 00728 uint32_t DataFlashBlockDevice::_translate_address(bd_addr_t addr) 00729 { 00730 uint32_t address = addr; 00731 00732 /* translate address if page size is non-binary */ 00733 if (_page_size == DATAFLASH_PAGE_SIZE_264) { 00734 address = ((addr / DATAFLASH_PAGE_SIZE_264) << DATAFLASH_PAGE_BIT_264) | 00735 (addr % DATAFLASH_PAGE_SIZE_264); 00736 } else if (_page_size == DATAFLASH_PAGE_SIZE_528) { 00737 address = ((addr / DATAFLASH_PAGE_SIZE_528) << DATAFLASH_PAGE_BIT_528) | 00738 (addr % DATAFLASH_PAGE_SIZE_528); 00739 } 00740 00741 return address; 00742 } 00743 00744 /** 00745 * @brief Internal function for printing out each bit set in status register. 00746 * 00747 * @param status Status register. 00748 */ 00749 void _print_status(uint16_t status) 00750 { 00751 #if DATAFLASH_DEBUG 00752 DEBUG_PRINTF("%04X\r\n", status); 00753 00754 /* device is ready (after write/erase) */ 00755 if (status & DATAFLASH_BIT_READY) { 00756 DEBUG_PRINTF("DATAFLASH_BIT_READY\r\n"); 00757 } 00758 00759 /* Buffer comparison failed */ 00760 if (status & DATAFLASH_BIT_COMPARE) { 00761 DEBUG_PRINTF("DATAFLASH_BIT_COMPARE\r\n"); 00762 } 00763 00764 /* device size is 2 MB */ 00765 if (status & DATAFLASH_STATUS_DENSITY_2_MBIT) { 00766 DEBUG_PRINTF("DATAFLASH_STATUS_DENSITY_2_MBIT\r\n"); 00767 } 00768 00769 /* device size is 4 MB */ 00770 if (status & DATAFLASH_STATUS_DENSITY_4_MBIT) { 00771 DEBUG_PRINTF("DATAFLASH_STATUS_DENSITY_4_MBIT\r\n"); 00772 } 00773 00774 /* device size is 8 MB */ 00775 if (status & DATAFLASH_STATUS_DENSITY_8_MBIT) { 00776 DEBUG_PRINTF("DATAFLASH_STATUS_DENSITY_8_MBIT\r\n"); 00777 } 00778 00779 /* device size is 16 MB */ 00780 if (status & DATAFLASH_STATUS_DENSITY_16_MBIT) { 00781 DEBUG_PRINTF("DATAFLASH_STATUS_DENSITY_16_MBIT\r\n"); 00782 } 00783 00784 /* device size is 32 MB */ 00785 if (status & DATAFLASH_STATUS_DENSITY_32_MBIT) { 00786 DEBUG_PRINTF("DATAFLASH_STATUS_DENSITY_32_MBIT\r\n"); 00787 } 00788 00789 /* device size is 64 MB */ 00790 if (status & DATAFLASH_STATUS_DENSITY_64_MBIT) { 00791 DEBUG_PRINTF("DATAFLASH_STATUS_DENSITY_64_MBIT\r\n"); 00792 } 00793 00794 /* sector protectino enabled */ 00795 if (status & DATAFLASH_BIT_PROTECT) { 00796 DEBUG_PRINTF("DATAFLASH_BIT_PROTECT\r\n"); 00797 } 00798 00799 /* page size is a power of 2 */ 00800 if (status & DATAFLASH_BIT_PAGE_SIZE) { 00801 DEBUG_PRINTF("DATAFLASH_BIT_PAGE_SIZE\r\n"); 00802 } 00803 00804 /* erase/program error */ 00805 if (status & DATAFLASH_BIT_ERASE_PROGRAM_ERROR) { 00806 DEBUG_PRINTF("DATAFLASH_BIT_ERASE_PROGRAM_ERROR\r\n"); 00807 } 00808 00809 /* sector lockdown still possible */ 00810 if (status & DATAFLASH_BIT_SECTOR_LOCKDOWN) { 00811 DEBUG_PRINTF("DATAFLASH_BIT_SECTOR_LOCKDOWN\r\n"); 00812 } 00813 00814 /* program operation suspended while using buffer 2 */ 00815 if (status & DATAFLASH_BIT_PROGRAM_SUSPEND_2) { 00816 DEBUG_PRINTF("DATAFLASH_BIT_PROGRAM_SUSPEND_2\r\n"); 00817 } 00818 00819 /* program operation suspended while using buffer 1 */ 00820 if (status & DATAFLASH_BIT_PROGRAM_SUSPEND_1) { 00821 DEBUG_PRINTF("DATAFLASH_BIT_PROGRAM_SUSPEND_1\r\n"); 00822 } 00823 00824 /* erase has been suspended */ 00825 if (status & DATAFLASH_BIT_ERASE_SUSPEND) { 00826 DEBUG_PRINTF("DATAFLASH_BIT_ERASE_SUSPEND\r\n"); 00827 } 00828 #endif 00829 }
Generated on Tue Jul 12 2022 13:54:16 by
1.7.2