Nut/OS  4.10.3
API Reference
spi_flash_at45d.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008-2011 by egnite GmbH
00003  *
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  * 2. Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in the
00014  *    documentation and/or other materials provided with the distribution.
00015  * 3. Neither the name of the copyright holders nor the names of
00016  *    contributors may be used to endorse or promote products derived
00017  *    from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00023  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00026  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00027  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00028  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00029  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030  * SUCH DAMAGE.
00031  *
00032  * For additional information see http://www.ethernut.de/
00033  */
00034 
00044 #include <cfg/memory.h>
00045 #include <sys/nutdebug.h>
00046 
00047 #include <dev/spi_node_at45d.h>
00048 
00049 #include <stdlib.h>
00050 #include <string.h>
00051 
00056 
00057 #ifndef FLASH_BUFFERS_AT45D
00058 #define FLASH_BUFFERS_AT45D  2
00059 #endif
00060 
00061 #ifdef AT45D_CRC_PAGE
00062 #define AT45D_CRC_SIZE  2
00063 #else
00064 #define AT45D_CRC_SIZE  0
00065 #endif
00066 
00068 #define FLASH_BUFFER_DIRTY      0x0001
00069 
00075 typedef struct _AT45D_FLASH {
00080     sf_unit_t dxb_page[FLASH_BUFFERS_AT45D];
00081 
00087     uint_fast8_t flags[FLASH_BUFFERS_AT45D];
00088 
00094     int dxb_locks[FLASH_BUFFERS_AT45D];
00095 
00100     HANDLE dxb_lque;
00101 
00107     uint_fast8_t dxb_pshft;
00108 
00110     uint8_t *dxb_pbuf[FLASH_BUFFERS_AT45D];
00111 } AT45D_FLASH;
00112 
00113 #ifdef AT45D_CRC_PAGE
00114 
00115 /*
00116  * http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html
00117  */
00118 static uint16_t crc_ccitt_update(uint16_t crc, uint8_t data)
00119 {
00120     data ^= (uint8_t) (crc);
00121     data ^= data << 4;
00122 
00123     return ((((uint16_t) data << 8) | (crc >> 8)) ^ (uint8_t) (data >> 4) ^ ((uint16_t) data << 3));
00124 }
00125 
00134 static int CalculateChecksum(AT45D_FLASH * at, int_fast8_t b, uint16_t * crc16, int xlen)
00135 {
00136     int rc;
00137     NUTSPIBUS *bus;
00138 
00139     /* Sanity checks. */
00140     NUTASSERT(at != NULL);
00141     NUTASSERT(crc16 != NULL);
00142 
00143     *crc16 = 0xffff;
00144     if (xlen) {
00145         int i;
00146         uint8_t c;
00147         uint_fast8_t ne = 0;
00148 
00149         for (i = 0; i < xlen; i++) {
00150             c = at->dxb_pbuf[i];
00151             if (ne || c != 0xff) {
00152                 ne = 1;
00153                 *crc16 = crc_ccitt_update(*crc16, c);
00154             }
00155         }
00156         if (*crc16 == 0) {
00157             *crc16 = 0xffff;
00158         }
00159     }
00160 }
00161 
00162 #endif                          /* AT45D_CRC_PAGE */
00163 
00172 static int At45dFlashSaveUnit(NUTSERIALFLASH * sfi, int_fast8_t b)
00173 {
00174     int rc;
00175     AT45D_FLASH *at;
00176 
00177     at = (AT45D_FLASH *) sfi->sf_info;
00178 
00179 #ifdef AT45D_CRC_PAGE
00180     /* Store a 16 bit CRC at the end of the page, if configured. */
00181     {
00182         uint16_t crc16;
00183 
00184         CalculateChecksum(at, b, &crc16, sfi->sf_unit_size);
00185         memcpy(at->dxb_pbuf[b] + sfi->sf_unit_size, &crc16, sizeof(crc16));
00186     }
00187 #endif
00188 
00189     rc = At45dNodeLock(sfi->sf_node);
00190     if (rc == 0) {
00191         rc = At45dNodeTransfer(sfi->sf_node, DFCMD_BUF2_WRITE, 0, 4, at->dxb_pbuf[b], NULL, sfi->sf_unit_size + AT45D_CRC_SIZE);
00192         if (rc == 0) {
00193             uint32_t pga;
00194 
00195             pga = at->dxb_page[b];
00196             pga <<= at->dxb_pshft;
00197             rc = At45dNodeCommand(sfi->sf_node, DFCMD_BUF2_FLASH_NE, pga, 4);
00198             if (rc == 0) {
00199                 rc = At45dNodeWaitReady(sfi->sf_node, AT45_WRITE_POLLS, 0);
00200             }
00201             At45dNodeUnlock(sfi->sf_node);
00202             if (rc == 0) {
00203                 at->flags[b] &= ~FLASH_BUFFER_DIRTY;
00204             }
00205         }
00206     }
00207     return rc;
00208 }
00209 
00216 static void At45dFlashRelease(NUTSERIALFLASH * sfi, int b)
00217 {
00218     AT45D_FLASH *at = (AT45D_FLASH *) sfi->sf_info;
00219 
00220     at->dxb_locks[b]--;
00221     NutEventPost(&at->dxb_lque);
00222 }
00223 
00241 static int_fast8_t At45dFlashLoadUnit(NUTSERIALFLASH * sfi, sf_unit_t pgn, int_fast8_t lock)
00242 {
00243     static int_fast8_t bnxt = 0;
00244     int_fast8_t b;
00245     AT45D_FLASH *at;
00246 
00247     at = (AT45D_FLASH *) sfi->sf_info;
00248     for (;;) {
00249         /*
00250          * Check, if the page is already loaded.
00251          */
00252         for (b = 0; b < FLASH_BUFFERS_AT45D; b++) {
00253             if (at->dxb_page[b] == pgn) {
00254                 if (lock) {
00255                     at->dxb_locks[b]++;
00256                     at->flags[b] |= FLASH_BUFFER_DIRTY;
00257                 }
00258                 return b;
00259             }
00260         }
00261 
00262         /*
00263          * Search for a clean unlocked buffer and load the page.
00264          */
00265         b = bnxt;
00266         do {
00267             if (at->dxb_locks[b] == 0 && (at->flags[b] & FLASH_BUFFER_DIRTY) == 0) {
00268                 break;
00269             }
00270             if (++b >= FLASH_BUFFERS_AT45D) {
00271                 b = 0;
00272             }
00273             if (b == bnxt) {
00274                 b = -1;
00275             }
00276         } while (b >= 0);
00277         if (b >= 0) {
00278             int rc;
00279             uint32_t pga = pgn;
00280 
00281             if (At45dNodeLock(sfi->sf_node) == 0) {
00282                 pga <<= at->dxb_pshft;
00283                 if (lock) {
00284                     at->dxb_locks[b]++;
00285                 }
00286                 rc = At45dNodeTransfer(sfi->sf_node, DFCMD_READ_PAGE, pga, 8, NULL, at->dxb_pbuf[b],
00287                                        sfi->sf_unit_size + AT45D_CRC_SIZE);
00288                 At45dNodeUnlock(sfi->sf_node);
00289                 if (rc == 0) {
00290                     at->dxb_page[b] = pgn;
00291                     if (lock) {
00292                         at->flags[b] |= FLASH_BUFFER_DIRTY;
00293                     }
00294                     if (++bnxt >= FLASH_BUFFERS_AT45D) {
00295                         bnxt = 0;
00296                     }
00297                     return b;
00298                 }
00299                 if (lock) {
00300                     At45dFlashRelease(sfi, b);
00301                 }
00302             }
00303             return -1;
00304         }
00305 
00306         /*
00307          * No clean buffer. If not locked, save one of them.
00308          */
00309         for (b = 0; b < FLASH_BUFFERS_AT45D; b++) {
00310             if (at->dxb_locks[b] == 0 && (at->flags[b] & FLASH_BUFFER_DIRTY) == FLASH_BUFFER_DIRTY) {
00311                 if (At45dFlashSaveUnit(sfi, b)) {
00312                     return -1;
00313                 }
00314                 break;
00315             }
00316         }
00317 
00318         /*
00319          * All buffers are locked. Wait for an unlock event.
00320          */
00321         if (b >= FLASH_BUFFERS_AT45D) {
00322             NutEventWait(&at->dxb_lque, 0);
00323         }
00324     }
00325 }
00326 
00334 static int SpiAt45dFlashInit(NUTSERIALFLASH * sfi)
00335 {
00336     int_fast8_t b;
00337     AT45D_INFO *df;
00338     AT45D_FLASH *at;
00339 
00340     /* Sanity checks. */
00341     NUTASSERT(sfi != NULL);
00342     NUTASSERT(sfi->sf_node != NULL);
00343 
00344     df = At45dNodeProbe(sfi->sf_node);
00345     if (df == NULL) {
00346         /* Unknown DataFlash type. */
00347         return -1;
00348     }
00349     /* Known DataFlash type. */
00350     at = calloc(1, sizeof(AT45D_FLASH));
00351     if (at == NULL) {
00352         return -1;
00353     }
00354     at->dxb_pshft = df->at45d_pshft;
00355     for (b = 0; b < FLASH_BUFFERS_AT45D; b++) {
00356         at->dxb_page[b] = SERIALFLASH_MAX_UNITS;
00357         at->dxb_pbuf[b] = malloc(df->at45d_psize);
00358     }
00359     sfi->sf_info = (void *) at;
00360     sfi->sf_units = (sf_unit_t) df->at45d_pages;
00361     sfi->sf_unit_size = df->at45d_psize - AT45D_CRC_SIZE;
00362 
00363     return 0;
00364 }
00365 
00371 static void SpiAt45dFlashExit(NUTSERIALFLASH * sfi)
00372 {
00373     int_fast8_t b;
00374     AT45D_FLASH *at;
00375 
00376     NUTASSERT(sfi != NULL);
00377     NUTASSERT(sfi->sf_info != NULL);
00378 
00379     at = (AT45D_FLASH *) sfi->sf_info;
00380     for (b = 0; b < FLASH_BUFFERS_AT45D; b++) {
00381         free(at->dxb_pbuf[b]);
00382     }
00383     free(sfi->sf_info);
00384 }
00385 
00396 static int SpiAt45dFlashCheck(NUTSERIALFLASH * sfi, sf_unit_t pgn, int cnt)
00397 {
00398     int rc = 0;
00399 
00400 #ifdef AT45D_CRC_PAGE
00401     AT45D_FLASH *at;
00402     int_fast8_t b;
00403     uint16_t crc16 = 0;
00404 
00405     /* Sanity checks. */
00406     NUTASSERT(sfi != NULL);
00407     NUTASSERT(sfi->sf_info != NULL);
00408     NUTASSERT(pgn + cnt <= sfi->sf_units);
00409     NUTASSERT(cnt >= 0);
00410 
00411     at = (AT45D_FLASH *) sfi->sf_info;
00412     while (cnt--) {
00413         b = At45dFlashLoadUnit(sfi, pgn + cnt, 0);
00414         if (b >= 0) {
00415             CalculateChecksum(at, b, &crc16, sfi->sf_unit_size + AT45D_CRC_SIZE);
00416         }
00417         if (crc16 != 0xFFFF) {
00418             rc = -1;
00419             break;
00420         }
00421     }
00422 #endif
00423     return rc;
00424 }
00425 
00438 static int SpiAt45dFlashRead(NUTSERIALFLASH * sfi, sf_unit_t pgn, int off, void *data, int len)
00439 {
00440     int rc = 0;
00441 
00442     /* Sanity checks. */
00443     NUTASSERT(sfi != NULL);
00444     NUTASSERT(sfi->sf_info != NULL);
00445     NUTASSERT(pgn < sfi->sf_units);
00446     NUTASSERT(off >= -(int) sfi->sf_unit_size && off <= (int) sfi->sf_unit_size);
00447     NUTASSERT(data != NULL);
00448     NUTASSERT(len >= 0 && len <= sfi->sf_unit_size);
00449 
00450     if (len) {
00451         int_fast8_t b;
00452         AT45D_FLASH *at = (AT45D_FLASH *) sfi->sf_info;
00453 
00454         /* Normalize the offset. */
00455         if (off < 0) {
00456             off += sfi->sf_unit_size;
00457         }
00458         NUTASSERT(off + len <= (int) sfi->sf_unit_size);
00459 
00460         b = At45dFlashLoadUnit(sfi, pgn, 0);
00461         if (b < 0) {
00462             rc = -1;
00463         } else {
00464             memcpy(data, at->dxb_pbuf[b] + off, len);
00465         }
00466     }
00467     return rc;
00468 }
00469 
00482 static int SpiAt45dFlashCompare(NUTSERIALFLASH * sfi, sf_unit_t pgn, int off, CONST void *data, int len)
00483 {
00484     int rc = 0;
00485 
00486     /* Sanity checks. */
00487     NUTASSERT(sfi != NULL);
00488     NUTASSERT(sfi->sf_info != NULL);
00489     NUTASSERT(pgn < sfi->sf_units);
00490     NUTASSERT(off >= -(int) sfi->sf_unit_size && off <= (int) sfi->sf_unit_size);
00491     NUTASSERT(data != NULL);
00492     NUTASSERT(len >= 0 && len <= sfi->sf_unit_size);
00493 
00494     if (len) {
00495         int_fast8_t b;
00496         AT45D_FLASH *at = (AT45D_FLASH *) sfi->sf_info;
00497 
00498         /* Normalize the offset. */
00499         if (off < 0) {
00500             off += sfi->sf_unit_size;
00501         }
00502         NUTASSERT(off + len <= (int) sfi->sf_unit_size);
00503 
00504         b = At45dFlashLoadUnit(sfi, pgn, 0);
00505         if (b < 0 || memcmp(at->dxb_pbuf[b] + off, data, len)) {
00506             rc = -1;
00507         }
00508     }
00509     return rc;
00510 }
00511 
00525 static int SpiAt45dFlashUsed(NUTSERIALFLASH * sfi, sf_unit_t pgn, int skip)
00526 {
00527     int rc;
00528     int len;
00529     AT45D_FLASH *at;
00530     int_fast8_t b;
00531 
00532     /* Sanity checks. */
00533     NUTASSERT(sfi != NULL);
00534     NUTASSERT(pgn < sfi->sf_units);
00535     NUTASSERT(skip <= (int) sfi->sf_unit_size);
00536 
00537     at = (AT45D_FLASH *) sfi->sf_info;
00538 
00539     /* Determine length and offset. */
00540     len = (int) sfi->sf_unit_size;
00541     if (skip < 0) {
00542         len += skip;
00543         skip = 0;
00544     } else {
00545         len -= skip;
00546     }
00547 
00548     b = At45dFlashLoadUnit(sfi, pgn, 0);
00549     if (b < 0) {
00550         rc = -1;
00551     } else {
00552         rc = 0;
00553         if (len) {
00554             uint8_t *cp = at->dxb_pbuf[b] + skip;
00555             int i;
00556 
00557             for (i = 0; i < len; i++) {
00558                 if (*cp++ != 0xff) {
00559                     rc = i + 1;
00560                 }
00561             }
00562         }
00563     }
00564     return rc;
00565 }
00566 
00583 static int SpiAt45dFlashWrite(NUTSERIALFLASH * sfi, sf_unit_t pgn, int off, CONST void *data, int len)
00584 {
00585     int rc = 0;
00586 
00587     /* Sanity checks. */
00588     NUTASSERT(sfi != NULL);
00589     NUTASSERT(pgn < sfi->sf_units);
00590     NUTASSERT(off >= -(int) sfi->sf_unit_size && off <= (int) sfi->sf_unit_size);
00591     NUTASSERT(len == 0 || data != NULL);
00592     NUTASSERT(len >= 0 && len <= sfi->sf_unit_size);
00593 
00594     if (len) {
00595         int_fast8_t b;
00596         AT45D_FLASH *at = (AT45D_FLASH *) sfi->sf_info;
00597 
00598         /* Normalize the offset. */
00599         if (off < 0) {
00600             off += sfi->sf_unit_size;
00601         }
00602         NUTASSERT(off + len <= (int) sfi->sf_unit_size);
00603 
00604         /* Load the page. */
00605         b = At45dFlashLoadUnit(sfi, pgn, 1);
00606         if (b < 0) {
00607             return -1;
00608         }
00609         /* Transfer the data and release the page. */
00610         memcpy(at->dxb_pbuf[b] + off, data, len);
00611         At45dFlashRelease(sfi, b);
00612     }
00613     return rc;
00614 }
00615 
00629 static int SpiAt45dFlashCopy(NUTSERIALFLASH * sfi, sf_unit_t spg, sf_unit_t dpg)
00630 {
00631     int_fast8_t b;
00632 
00633     /* Sanity checks. */
00634     NUTASSERT(sfi != NULL);
00635     NUTASSERT(sfi->sf_info != NULL);
00636     NUTASSERT(spg < sfi->sf_units);
00637     NUTASSERT(dpg < sfi->sf_units);
00638 
00639     /* If source and destination page numbers are equal, just load it. */
00640     if (spg == dpg) {
00641         b = At45dFlashLoadUnit(sfi, spg, 1);
00642     } else {
00643         AT45D_FLASH *at = (AT45D_FLASH *) sfi->sf_info;
00644 
00645         /* Invalidate any buffered destination. */
00646         for (b = 0; b < FLASH_BUFFERS_AT45D; b++) {
00647             if (at->dxb_page[b] == dpg) {
00648                 /* But do not touch locked pages. */
00649                 if (at->dxb_locks[b]) {
00650                     return -1;
00651                 }
00652                 at->dxb_page[b] = SERIALFLASH_MAX_UNITS;
00653             }
00654         }
00655         /* Try to load the source page and make it the destination page. */
00656         b = At45dFlashLoadUnit(sfi, spg, 1);
00657         if (b >= 0) {
00658             at->dxb_page[b] = dpg;
00659         }
00660     }
00661     if (b >= 0) {
00662         At45dFlashRelease(sfi, b);
00663         return 0;
00664     }
00665     return -1;
00666 }
00667 
00680 static int SpiAt45dFlashCommit(NUTSERIALFLASH * sfi, sf_unit_t pgn)
00681 {
00682     int rc = 0;
00683     int_fast8_t b;
00684     AT45D_FLASH *at;
00685 
00686     /* Sanity checks. */
00687     NUTASSERT(sfi != NULL);
00688     NUTASSERT(pgn < sfi->sf_units);
00689 
00690     at = (AT45D_FLASH *) sfi->sf_info;
00691     for (b = 0; b < FLASH_BUFFERS_AT45D && at->dxb_page[b] != pgn; b++);
00692     if (b < FLASH_BUFFERS_AT45D && (at->flags[b] & FLASH_BUFFER_DIRTY) == FLASH_BUFFER_DIRTY) {
00693         rc = At45dFlashSaveUnit(sfi, b);
00694     }
00695     return rc;
00696 }
00697 
00707 static int SpiAt45dFlashErase(NUTSERIALFLASH * sfi, sf_unit_t pgn, int cnt)
00708 {
00709     int rc = 0;
00710     int_fast8_t b;
00711     AT45D_FLASH *at;
00712 
00713     /* Sanity checks. */
00714     NUTASSERT(sfi != NULL);
00715     NUTASSERT(pgn + cnt <= sfi->sf_units);
00716     NUTASSERT(cnt >= 0);
00717 
00718     at = (AT45D_FLASH *) sfi->sf_info;
00719     /* Invalidate any buffered page. */
00720     for (b = 0; b < FLASH_BUFFERS_AT45D; b++) {
00721         if (at->dxb_page[b] >= pgn && at->dxb_page[b] < pgn + cnt) {
00722             at->dxb_page[b] = SERIALFLASH_MAX_UNITS;
00723             at->flags[b] &= ~FLASH_BUFFER_DIRTY;
00724         }
00725     }
00726     while (rc == 0 && cnt--) {
00727         uint32_t pga = pgn + cnt;
00728         pga <<= at->dxb_pshft;
00729 
00730         rc = At45dNodeLock(sfi->sf_node);
00731         if (rc == 0) {
00732             rc = At45dNodeCommand(sfi->sf_node, DFCMD_PAGE_ERASE, pga, 4);
00733             if (rc == 0) {
00734                 At45dNodeWaitReady(sfi->sf_node, AT45_WRITE_POLLS, 0);
00735             }
00736             At45dNodeUnlock(sfi->sf_node);
00737         }
00738     }
00739     return rc;
00740 }
00741 
00742 #ifndef FLASH_MOUNT_OFFSET_AT45D0
00743 #ifdef MOUNT_OFFSET_AT45D0
00744 #define FLASH_MOUNT_OFFSET_AT45D0       MOUNT_OFFSET_AT45D0
00745 #else
00746 #define FLASH_MOUNT_OFFSET_AT45D0       0
00747 #endif
00748 #endif
00749 
00750 #ifndef FLASH_MOUNT_TOP_RESERVE_AT45D0
00751 #ifdef MOUNT_TOP_RESERVE_AT45D0
00752 #define FLASH_MOUNT_TOP_RESERVE_AT45D0  MOUNT_TOP_RESERVE_AT45D0
00753 #else
00754 #define FLASH_MOUNT_TOP_RESERVE_AT45D0  1
00755 #endif
00756 #endif
00757 
00761 NUTSERIALFLASH flashAt45d0 = {
00762     &nodeAt45d0,                
00763     NULL,                       
00764     0,                          
00765     0,                          
00766     FLASH_MOUNT_OFFSET_AT45D0,  
00767     FLASH_MOUNT_TOP_RESERVE_AT45D0,     
00768     SpiAt45dFlashInit,          
00769     SpiAt45dFlashExit,          
00770     SpiAt45dFlashCheck,         
00771     SpiAt45dFlashRead,          
00772     SpiAt45dFlashCompare,       
00773     SpiAt45dFlashUsed,          
00774     SpiAt45dFlashWrite,         
00775     SpiAt45dFlashCopy,          
00776     SpiAt45dFlashCommit,        
00777     SpiAt45dFlashErase          
00778 };
00779 
00780 #ifndef FLASH_MOUNT_OFFSET_AT45D1
00781 #ifdef MOUNT_OFFSET_AT45D1
00782 #define FLASH_MOUNT_OFFSET_AT45D1       MOUNT_OFFSET_AT45D1
00783 #else
00784 #define FLASH_MOUNT_OFFSET_AT45D1       0
00785 #endif
00786 #endif
00787 
00788 #ifndef FLASH_MOUNT_TOP_RESERVE_AT45D1
00789 #ifdef MOUNT_TOP_RESERVE_AT45D1
00790 #define FLASH_MOUNT_TOP_RESERVE_AT45D1  MOUNT_TOP_RESERVE_AT45D1
00791 #else
00792 #define FLASH_MOUNT_TOP_RESERVE_AT45D1  1
00793 #endif
00794 #endif
00795 
00799 NUTSERIALFLASH flashAt45d1 = {
00800     &nodeAt45d1,                
00801     NULL,                       
00802     0,                          
00803     0,                          
00804     FLASH_MOUNT_OFFSET_AT45D1,  
00805     FLASH_MOUNT_TOP_RESERVE_AT45D1,     
00806     SpiAt45dFlashInit,          
00807     SpiAt45dFlashExit,          
00808     SpiAt45dFlashCheck,         
00809     SpiAt45dFlashRead,          
00810     SpiAt45dFlashCompare,       
00811     SpiAt45dFlashUsed,          
00812     SpiAt45dFlashWrite,         
00813     SpiAt45dFlashCopy,          
00814     SpiAt45dFlashCommit,        
00815     SpiAt45dFlashErase          
00816 };
00817 
00818 #ifndef FLASH_MOUNT_OFFSET_AT45D2
00819 #ifdef MOUNT_OFFSET_AT45D2
00820 #define FLASH_MOUNT_OFFSET_AT45D2       MOUNT_OFFSET_AT45D2
00821 #else
00822 #define FLASH_MOUNT_OFFSET_AT45D2       0
00823 #endif
00824 #endif
00825 
00826 #ifndef FLASH_MOUNT_TOP_RESERVE_AT45D2
00827 #ifdef MOUNT_TOP_RESERVE_AT45D2
00828 #define FLASH_MOUNT_TOP_RESERVE_AT45D2  MOUNT_TOP_RESERVE_AT45D2
00829 #else
00830 #define FLASH_MOUNT_TOP_RESERVE_AT45D2  1
00831 #endif
00832 #endif
00833 
00837 NUTSERIALFLASH flashAt45d2 = {
00838     &nodeAt45d2,                
00839     NULL,                       
00840     0,                          
00841     0,                          
00842     FLASH_MOUNT_OFFSET_AT45D2,  
00843     FLASH_MOUNT_TOP_RESERVE_AT45D2,     
00844     SpiAt45dFlashInit,          
00845     SpiAt45dFlashExit,          
00846     SpiAt45dFlashCheck,         
00847     SpiAt45dFlashRead,          
00848     SpiAt45dFlashCompare,       
00849     SpiAt45dFlashUsed,          
00850     SpiAt45dFlashWrite,         
00851     SpiAt45dFlashCopy,          
00852     SpiAt45dFlashCommit,        
00853     SpiAt45dFlashErase          
00854 };
00855 
00856 #ifndef FLASH_MOUNT_OFFSET_AT45D3
00857 #ifdef MOUNT_OFFSET_AT45D3
00858 #define FLASH_MOUNT_OFFSET_AT45D3       MOUNT_OFFSET_AT45D3
00859 #else
00860 #define FLASH_MOUNT_OFFSET_AT45D3       0
00861 #endif
00862 #endif
00863 
00864 #ifndef FLASH_MOUNT_TOP_RESERVE_AT45D3
00865 #ifdef MOUNT_TOP_RESERVE_AT45D3
00866 #define FLASH_MOUNT_TOP_RESERVE_AT45D3  MOUNT_TOP_RESERVE_AT45D3
00867 #else
00868 #define FLASH_MOUNT_TOP_RESERVE_AT45D3  1
00869 #endif
00870 #endif
00871 
00875 NUTSERIALFLASH flashAt45d3 = {
00876     &nodeAt45d3,                
00877     NULL,                       
00878     0,                          
00879     0,                          
00880     FLASH_MOUNT_OFFSET_AT45D3,  
00881     FLASH_MOUNT_TOP_RESERVE_AT45D3,     
00882     SpiAt45dFlashInit,          
00883     SpiAt45dFlashExit,          
00884     SpiAt45dFlashCheck,         
00885     SpiAt45dFlashRead,          
00886     SpiAt45dFlashCompare,       
00887     SpiAt45dFlashUsed,          
00888     SpiAt45dFlashWrite,         
00889     SpiAt45dFlashCopy,          
00890     SpiAt45dFlashCommit,        
00891     SpiAt45dFlashErase          
00892 };
00893