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