Kev Mann / mbed-dev-OS5_10_4
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     _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 }