takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DataFlashBlockDevice.cpp Source File

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 }