Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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_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 }