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 DEBUG_PRINTF("init\r\n"); 00168 00169 if (!_is_initialized) { 00170 _init_ref_count = 0; 00171 } 00172 00173 uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); 00174 00175 if (val != 1) { 00176 return BD_ERROR_OK; 00177 } 00178 00179 int result = BD_ERROR_DEVICE_ERROR; 00180 00181 /* read ID register to validate model and set dimensions */ 00182 uint16_t id = _get_register(DATAFLASH_OP_ID); 00183 00184 DEBUG_PRINTF("id: %04X\r\n", id & DATAFLASH_ID_MATCH); 00185 00186 /* get status register to verify the page size mode */ 00187 uint16_t status = _get_register(DATAFLASH_OP_STATUS); 00188 00189 /* manufacture ID match */ 00190 if ((id & DATAFLASH_ID_MATCH) == DATAFLASH_ID_MATCH) { 00191 00192 /* calculate density */ 00193 _device_size = 0x8000 << (id & DATAFLASH_ID_DENSITY_MASK); 00194 00195 bool binary_page_size = true; 00196 00197 /* check if device is configured for binary page sizes */ 00198 if ((status & DATAFLASH_BIT_PAGE_SIZE) == DATAFLASH_BIT_PAGE_SIZE) { 00199 DEBUG_PRINTF("Page size is binary\r\n"); 00200 00201 #if MBED_CONF_DATAFLASH_DATAFLASH_SIZE 00202 /* send reconfiguration command */ 00203 _write_command(DATAFLASH_COMMAND_DATAFLASH_PAGE_SIZE, NULL, 0); 00204 00205 /* wait for device to be ready and update return code */ 00206 result = _sync(); 00207 00208 /* set binary flag */ 00209 binary_page_size = false; 00210 #else 00211 /* set binary flag */ 00212 binary_page_size = true; 00213 #endif 00214 } else { 00215 DEBUG_PRINTF("Page size is not binary\r\n"); 00216 00217 #if MBED_CONF_DATAFLASH_BINARY_SIZE 00218 /* send reconfiguration command */ 00219 _write_command(DATAFLASH_COMMAND_BINARY_PAGE_SIZE, NULL, 0); 00220 00221 /* wait for device to be ready and update return code */ 00222 result = _sync(); 00223 00224 /* set binary flag */ 00225 binary_page_size = true; 00226 #else 00227 /* set binary flag */ 00228 binary_page_size = false; 00229 #endif 00230 } 00231 00232 /* set page program size and block erase size */ 00233 switch (id & DATAFLASH_ID_DENSITY_MASK) { 00234 case DATAFLASH_ID_DENSITY_2_MBIT: 00235 case DATAFLASH_ID_DENSITY_4_MBIT: 00236 case DATAFLASH_ID_DENSITY_8_MBIT: 00237 case DATAFLASH_ID_DENSITY_64_MBIT: 00238 if (binary_page_size) { 00239 _page_size = DATAFLASH_PAGE_SIZE_256; 00240 _block_size = DATAFLASH_BLOCK_SIZE_2K; 00241 } else { 00242 _page_size = DATAFLASH_PAGE_SIZE_264; 00243 _block_size = DATAFLASH_BLOCK_SIZE_2K1; 00244 00245 /* adjust device size */ 00246 _device_size = (_device_size / DATAFLASH_PAGE_SIZE_256) * 00247 DATAFLASH_PAGE_SIZE_264; 00248 } 00249 break; 00250 case DATAFLASH_ID_DENSITY_16_MBIT: 00251 case DATAFLASH_ID_DENSITY_32_MBIT: 00252 if (binary_page_size) { 00253 _page_size = DATAFLASH_PAGE_SIZE_512; 00254 _block_size = DATAFLASH_BLOCK_SIZE_4K; 00255 } else { 00256 _page_size = DATAFLASH_PAGE_SIZE_528; 00257 _block_size = DATAFLASH_BLOCK_SIZE_4K1; 00258 00259 /* adjust device size */ 00260 _device_size = (_device_size / DATAFLASH_PAGE_SIZE_512) * 00261 DATAFLASH_PAGE_SIZE_528; 00262 } 00263 break; 00264 default: 00265 break; 00266 } 00267 00268 DEBUG_PRINTF("density: %" PRIu16 "\r\n", id & DATAFLASH_ID_DENSITY_MASK); 00269 DEBUG_PRINTF("size: %" PRIu32 "\r\n", _device_size); 00270 DEBUG_PRINTF("page: %" PRIu16 "\r\n", _page_size); 00271 DEBUG_PRINTF("block: %" PRIu16 "\r\n", _block_size); 00272 00273 /* device successfully detected, set OK error code */ 00274 result = BD_ERROR_OK; 00275 } 00276 00277 /* write protect device when idle */ 00278 _write_enable(false); 00279 00280 if (result == BD_ERROR_OK) { 00281 _is_initialized = true; 00282 } 00283 00284 return result; 00285 } 00286 00287 int DataFlashBlockDevice::deinit() 00288 { 00289 DEBUG_PRINTF("deinit\r\n"); 00290 00291 if (!_is_initialized) { 00292 _init_ref_count = 0; 00293 return BD_ERROR_OK; 00294 } 00295 00296 uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); 00297 00298 if (val) { 00299 return BD_ERROR_OK; 00300 } 00301 00302 _is_initialized = false; 00303 return BD_ERROR_OK; 00304 } 00305 00306 int DataFlashBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) 00307 { 00308 DEBUG_PRINTF("read: %p %" PRIX64 " %" PRIX64 "\r\n", buffer, addr, size); 00309 00310 if (!_is_initialized) { 00311 return BD_ERROR_DEVICE_ERROR; 00312 } 00313 00314 int result = BD_ERROR_DEVICE_ERROR; 00315 00316 /* check parameters are valid and the read is within bounds */ 00317 if (is_valid_read(addr, size) && buffer) { 00318 00319 uint8_t *external_buffer = static_cast<uint8_t *>(buffer); 00320 00321 /* activate device */ 00322 _cs = 0; 00323 00324 /* send read opcode */ 00325 _spi.write(DATAFLASH_OP_READ_LOW_FREQUENCY); 00326 00327 /* translate address */ 00328 uint32_t address = _translate_address(addr); 00329 00330 DEBUG_PRINTF("address: %" PRIX32 "\r\n", address); 00331 00332 /* send read address */ 00333 _spi.write((address >> 16) & 0xFF); 00334 _spi.write((address >> 8) & 0xFF); 00335 _spi.write(address & 0xFF); 00336 00337 /* clock out one byte at a time and store in external buffer */ 00338 for (uint32_t index = 0; index < size; index++) { 00339 external_buffer[index] = _spi.write(DATAFLASH_OP_NOP); 00340 } 00341 00342 /* deactivate device */ 00343 _cs = 1; 00344 00345 result = BD_ERROR_OK; 00346 } 00347 00348 return result; 00349 } 00350 00351 int DataFlashBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) 00352 { 00353 DEBUG_PRINTF("program: %p %" PRIX64 " %" PRIX64 "\r\n", buffer, addr, size); 00354 00355 if (!_is_initialized) { 00356 return BD_ERROR_DEVICE_ERROR; 00357 } 00358 00359 int result = BD_ERROR_DEVICE_ERROR; 00360 00361 /* check parameters are valid and the write is within bounds */ 00362 if (is_valid_program(addr, size) && buffer) { 00363 00364 const uint8_t *external_buffer = static_cast<const uint8_t *>(buffer); 00365 00366 /* Each write command can only cover one page at a time. 00367 Find page and current page offset for handling unaligned writes. 00368 */ 00369 uint32_t page_number = addr / _page_size; 00370 uint32_t page_offset = addr % _page_size; 00371 00372 /* disable write protection */ 00373 _write_enable(true); 00374 00375 /* continue until all bytes have been written */ 00376 uint32_t bytes_written = 0; 00377 while (bytes_written < size) { 00378 00379 /* find remaining bytes to be written */ 00380 uint32_t bytes_remaining = size - bytes_written; 00381 00382 /* cap the value at the page size and offset */ 00383 if (bytes_remaining > (_page_size - page_offset)) { 00384 bytes_remaining = _page_size - page_offset; 00385 } 00386 00387 /* Write one page, bytes_written keeps track of the progress, 00388 page_number is the page address, and page_offset is non-zero for 00389 unaligned writes. 00390 */ 00391 result = _write_page(&external_buffer[bytes_written], 00392 page_number, 00393 page_offset, 00394 bytes_remaining); 00395 00396 /* update loop variables upon success otherwise break loop */ 00397 if (result == BD_ERROR_OK) { 00398 bytes_written += bytes_remaining; 00399 page_number++; 00400 00401 /* After the first successful write, 00402 all subsequent writes will be aligned. 00403 */ 00404 page_offset = 0; 00405 } else { 00406 break; 00407 } 00408 } 00409 00410 /* enable write protection */ 00411 _write_enable(false); 00412 } 00413 00414 return result; 00415 } 00416 00417 int DataFlashBlockDevice::erase(bd_addr_t addr, bd_size_t size) 00418 { 00419 DEBUG_PRINTF("erase: %" PRIX64 " %" PRIX64 "\r\n", addr, size); 00420 00421 if (!_is_initialized) { 00422 return BD_ERROR_DEVICE_ERROR; 00423 } 00424 00425 int result = BD_ERROR_DEVICE_ERROR; 00426 00427 /* check parameters are valid and the erase is within bounds */ 00428 if (is_valid_erase(addr, size)) { 00429 00430 /* disable write protection */ 00431 _write_enable(true); 00432 00433 /* erase one block at a time until the full size has been erased */ 00434 uint32_t erased = 0; 00435 while (erased < size) { 00436 00437 /* set block erase opcode */ 00438 uint32_t command = DATAFLASH_OP_ERASE_BLOCK; 00439 00440 /* translate address */ 00441 uint32_t address = _translate_address(addr); 00442 00443 /* set block address */ 00444 command = (command << 8) | ((address >> 16) & 0xFF); 00445 command = (command << 8) | ((address >> 8) & 0xFF); 00446 command = (command << 8) | (address & 0xFF); 00447 00448 /* send command to device */ 00449 _write_command(command, NULL, 0); 00450 00451 /* wait until device is ready and update return value */ 00452 result = _sync(); 00453 00454 /* if erase failed, break loop */ 00455 if (result != BD_ERROR_OK) { 00456 break; 00457 } 00458 00459 /* update loop variables */ 00460 addr += _block_size; 00461 erased += _block_size; 00462 } 00463 00464 /* enable write protection */ 00465 _write_enable(false); 00466 } 00467 00468 return result; 00469 } 00470 00471 bd_size_t DataFlashBlockDevice::get_read_size() const 00472 { 00473 DEBUG_PRINTF("read size: %d\r\n", DATAFLASH_READ_SIZE); 00474 00475 return DATAFLASH_READ_SIZE; 00476 } 00477 00478 bd_size_t DataFlashBlockDevice::get_program_size() const 00479 { 00480 DEBUG_PRINTF("program size: %d\r\n", DATAFLASH_PROG_SIZE); 00481 00482 return DATAFLASH_PROG_SIZE; 00483 } 00484 00485 bd_size_t DataFlashBlockDevice::get_erase_size() const 00486 { 00487 DEBUG_PRINTF("erase size: %" PRIX16 "\r\n", _block_size); 00488 00489 return _block_size; 00490 } 00491 00492 bd_size_t DataFlashBlockDevice::get_erase_size(bd_addr_t addr) const 00493 { 00494 DEBUG_PRINTF("erase size: %" PRIX16 "\r\n", _block_size); 00495 00496 return _block_size; 00497 } 00498 00499 bd_size_t DataFlashBlockDevice::size() const 00500 { 00501 DEBUG_PRINTF("device size: %" PRIX32 "\r\n", _device_size); 00502 00503 return _device_size; 00504 } 00505 00506 /** 00507 * @brief Function for reading a specific register. 00508 * @details Used for reading either the Status Register or Manufacture and ID Register. 00509 * 00510 * @param opcode Register to be read. 00511 * @return value. 00512 */ 00513 uint16_t DataFlashBlockDevice::_get_register(uint8_t opcode) 00514 { 00515 DEBUG_PRINTF("_get_register: %" PRIX8 "\r\n", opcode); 00516 00517 /* activate device */ 00518 _cs = 0; 00519 00520 /* write opcode */ 00521 _spi.write(opcode); 00522 00523 /* read and store result */ 00524 int status = (_spi.write(DATAFLASH_OP_NOP)); 00525 status = (status << 8) | (_spi.write(DATAFLASH_OP_NOP)); 00526 00527 /* deactivate device */ 00528 _cs = 1; 00529 00530 return status; 00531 } 00532 00533 /** 00534 * @brief Function for sending command and data to device. 00535 * @details The command can be an opcode with address and data or 00536 * a 4 byte command without data. 00537 * 00538 * The supported frequencies and the opcode used do not 00539 * require dummy bytes to be sent after command. 00540 * 00541 * @param command Opcode with address or 4 byte command. 00542 * @param buffer Data to be sent after command. 00543 * @param size Size of buffer. 00544 */ 00545 void DataFlashBlockDevice::_write_command(uint32_t command, const uint8_t *buffer, uint32_t size) 00546 { 00547 DEBUG_PRINTF("_write_command: %" PRIX32 " %p %" PRIX32 "\r\n", command, buffer, size); 00548 00549 /* activate device */ 00550 _cs = 0; 00551 00552 /* send command (opcode with data or 4 byte command) */ 00553 _spi.write((command >> 24) & 0xFF); 00554 _spi.write((command >> 16) & 0xFF); 00555 _spi.write((command >> 8) & 0xFF); 00556 _spi.write(command & 0xFF); 00557 00558 /* send optional data */ 00559 if (buffer && size) { 00560 for (uint32_t index = 0; index < size; index++) { 00561 _spi.write(buffer[index]); 00562 } 00563 } 00564 00565 /* deactivate device */ 00566 _cs = 1; 00567 } 00568 00569 /** 00570 * @brief Enable and disable write protection. 00571 * 00572 * @param enable Boolean for enabling or disabling write protection. 00573 */ 00574 void DataFlashBlockDevice::_write_enable(bool enable) 00575 { 00576 DEBUG_PRINTF("_write_enable: %d\r\n", enable); 00577 00578 /* enable writing, disable write protection */ 00579 if (enable) { 00580 /* if not-write-protected pin is connected, select it */ 00581 if (_nwp.is_connected()) { 00582 _nwp = 1; 00583 } 00584 00585 /* send 4 byte command enabling writes */ 00586 _write_command(DATAFLASH_COMMAND_WRITE_ENABLE, NULL, 0); 00587 } else { 00588 00589 /* if not-write-protected pin is connected, deselect it */ 00590 if (_nwp.is_connected()) { 00591 _nwp = 0; 00592 } 00593 00594 /* send 4 byte command disabling writes */ 00595 _write_command(DATAFLASH_COMMAND_WRITE_DISABLE, NULL, 0); 00596 } 00597 } 00598 00599 /** 00600 * @brief Sleep and poll status register until device is ready for next command. 00601 * 00602 * @return BlockDevice compatible error code. 00603 */ 00604 int DataFlashBlockDevice::_sync(void) 00605 { 00606 DEBUG_PRINTF("_sync\r\n"); 00607 00608 /* default return value if operation times out */ 00609 int result = BD_ERROR_DEVICE_ERROR; 00610 00611 /* Poll device until a hard coded timeout is reached. 00612 The polling interval is based on the typical page program time. 00613 */ 00614 for (uint32_t timeout = 0; 00615 timeout < DATAFLASH_TIMEOUT; 00616 timeout += DATAFLASH_TIMING_ERASE_PROGRAM_PAGE) { 00617 00618 /* get status register */ 00619 uint16_t status = _get_register(DATAFLASH_OP_STATUS); 00620 00621 /* erase/program bit set, exit with error code set */ 00622 if (status & DATAFLASH_BIT_ERASE_PROGRAM_ERROR) { 00623 DEBUG_PRINTF("DATAFLASH_BIT_ERASE_PROGRAM_ERROR\r\n"); 00624 break; 00625 /* device ready, set OK code set */ 00626 } else if (status & DATAFLASH_BIT_READY) { 00627 DEBUG_PRINTF("DATAFLASH_BIT_READY\r\n"); 00628 result = BD_ERROR_OK; 00629 break; 00630 /* wait the typical write period before trying again */ 00631 } else { 00632 DEBUG_PRINTF("wait_ms: %d\r\n", DATAFLASH_TIMING_ERASE_PROGRAM_PAGE); 00633 wait_ms(DATAFLASH_TIMING_ERASE_PROGRAM_PAGE); 00634 } 00635 } 00636 00637 return result; 00638 } 00639 00640 /** 00641 * @brief Write single page. 00642 * @details Address can be unaligned. 00643 * 00644 * @param buffer Data to write. 00645 * @param addr Address to write from. 00646 * @param size Bytes to write. Can at most be the full page. 00647 * @return BlockDevice error code. 00648 */ 00649 int DataFlashBlockDevice::_write_page(const uint8_t *buffer, 00650 uint32_t page, 00651 uint32_t offset, 00652 uint32_t size) 00653 { 00654 DEBUG_PRINTF("_write_page: %p %" PRIX32 " %" PRIX32 "\r\n", buffer, page, size); 00655 00656 uint32_t command = DATAFLASH_OP_NOP; 00657 00658 /* opcode for writing directly to device, in a single command, 00659 assuming the page has been erased before hand. 00660 */ 00661 command = DATAFLASH_OP_PROGRAM_DIRECT; 00662 00663 uint32_t address = 0; 00664 00665 /* convert page number and offset into device address based on address format */ 00666 if (_page_size == DATAFLASH_PAGE_SIZE_264) { 00667 address = (page << DATAFLASH_PAGE_BIT_264) | offset; 00668 } else if (_page_size == DATAFLASH_PAGE_SIZE_528) { 00669 address = (page << DATAFLASH_PAGE_BIT_528) | offset; 00670 } else { 00671 address = (page * _page_size) | offset; 00672 } 00673 00674 /* set write address */ 00675 command = (command << 8) | ((address >> 16) & 0xFF); 00676 command = (command << 8) | ((address >> 8) & 0xFF); 00677 command = (command << 8) | (address & 0xFF); 00678 00679 /* send write command with data */ 00680 _write_command(command, buffer, size); 00681 00682 /* wait until device is ready before continuing */ 00683 int result = _sync(); 00684 00685 return result; 00686 } 00687 00688 /** 00689 * @brief Translate address. 00690 * @details If the device is configured for non-binary page sizes, 00691 * the address is translated from binary to non-binary form. 00692 * 00693 * @param addr Binary address. 00694 * @return Address in format expected by device. 00695 */ 00696 uint32_t DataFlashBlockDevice::_translate_address(bd_addr_t addr) 00697 { 00698 uint32_t address = addr; 00699 00700 /* translate address if page size is non-binary */ 00701 if (_page_size == DATAFLASH_PAGE_SIZE_264) { 00702 address = ((addr / DATAFLASH_PAGE_SIZE_264) << DATAFLASH_PAGE_BIT_264) | 00703 (addr % DATAFLASH_PAGE_SIZE_264); 00704 } else if (_page_size == DATAFLASH_PAGE_SIZE_528) { 00705 address = ((addr / DATAFLASH_PAGE_SIZE_528) << DATAFLASH_PAGE_BIT_528) | 00706 (addr % DATAFLASH_PAGE_SIZE_528); 00707 } 00708 00709 return address; 00710 } 00711 00712 /** 00713 * @brief Internal function for printing out each bit set in status register. 00714 * 00715 * @param status Status register. 00716 */ 00717 void _print_status(uint16_t status) 00718 { 00719 #if DATAFLASH_DEBUG 00720 DEBUG_PRINTF("%04X\r\n", status); 00721 00722 /* device is ready (after write/erase) */ 00723 if (status & DATAFLASH_BIT_READY) { 00724 DEBUG_PRINTF("DATAFLASH_BIT_READY\r\n"); 00725 } 00726 00727 /* Buffer comparison failed */ 00728 if (status & DATAFLASH_BIT_COMPARE) { 00729 DEBUG_PRINTF("DATAFLASH_BIT_COMPARE\r\n"); 00730 } 00731 00732 /* device size is 2 MB */ 00733 if (status & DATAFLASH_STATUS_DENSITY_2_MBIT) { 00734 DEBUG_PRINTF("DATAFLASH_STATUS_DENSITY_2_MBIT\r\n"); 00735 } 00736 00737 /* device size is 4 MB */ 00738 if (status & DATAFLASH_STATUS_DENSITY_4_MBIT) { 00739 DEBUG_PRINTF("DATAFLASH_STATUS_DENSITY_4_MBIT\r\n"); 00740 } 00741 00742 /* device size is 8 MB */ 00743 if (status & DATAFLASH_STATUS_DENSITY_8_MBIT) { 00744 DEBUG_PRINTF("DATAFLASH_STATUS_DENSITY_8_MBIT\r\n"); 00745 } 00746 00747 /* device size is 16 MB */ 00748 if (status & DATAFLASH_STATUS_DENSITY_16_MBIT) { 00749 DEBUG_PRINTF("DATAFLASH_STATUS_DENSITY_16_MBIT\r\n"); 00750 } 00751 00752 /* device size is 32 MB */ 00753 if (status & DATAFLASH_STATUS_DENSITY_32_MBIT) { 00754 DEBUG_PRINTF("DATAFLASH_STATUS_DENSITY_32_MBIT\r\n"); 00755 } 00756 00757 /* device size is 64 MB */ 00758 if (status & DATAFLASH_STATUS_DENSITY_64_MBIT) { 00759 DEBUG_PRINTF("DATAFLASH_STATUS_DENSITY_64_MBIT\r\n"); 00760 } 00761 00762 /* sector protectino enabled */ 00763 if (status & DATAFLASH_BIT_PROTECT) { 00764 DEBUG_PRINTF("DATAFLASH_BIT_PROTECT\r\n"); 00765 } 00766 00767 /* page size is a power of 2 */ 00768 if (status & DATAFLASH_BIT_PAGE_SIZE) { 00769 DEBUG_PRINTF("DATAFLASH_BIT_PAGE_SIZE\r\n"); 00770 } 00771 00772 /* erase/program error */ 00773 if (status & DATAFLASH_BIT_ERASE_PROGRAM_ERROR) { 00774 DEBUG_PRINTF("DATAFLASH_BIT_ERASE_PROGRAM_ERROR\r\n"); 00775 } 00776 00777 /* sector lockdown still possible */ 00778 if (status & DATAFLASH_BIT_SECTOR_LOCKDOWN) { 00779 DEBUG_PRINTF("DATAFLASH_BIT_SECTOR_LOCKDOWN\r\n"); 00780 } 00781 00782 /* program operation suspended while using buffer 2 */ 00783 if (status & DATAFLASH_BIT_PROGRAM_SUSPEND_2) { 00784 DEBUG_PRINTF("DATAFLASH_BIT_PROGRAM_SUSPEND_2\r\n"); 00785 } 00786 00787 /* program operation suspended while using buffer 1 */ 00788 if (status & DATAFLASH_BIT_PROGRAM_SUSPEND_1) { 00789 DEBUG_PRINTF("DATAFLASH_BIT_PROGRAM_SUSPEND_1\r\n"); 00790 } 00791 00792 /* erase has been suspended */ 00793 if (status & DATAFLASH_BIT_ERASE_SUSPEND) { 00794 DEBUG_PRINTF("DATAFLASH_BIT_ERASE_SUSPEND\r\n"); 00795 } 00796 #endif 00797 }
Generated on Tue Aug 9 2022 00:37:05 by
