00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00044 #include <cfg/memory.h>
00045
00046 #include <sys/nutdebug.h>
00047 #include <dev/at45d.h>
00048 #ifndef DFCMD_BUF1_LOAD_PAGE
00049 #define DFCMD_BUF1_LOAD_PAGE 0x53
00050 #endif
00051 #ifndef DFCMD_BUF2_LOAD_PAGE
00052 #define DFCMD_BUF2_LOAD_PAGE 0x55
00053 #endif
00054 #include <stdlib.h>
00055
00056 #include <dev/spi_at45dib.h>
00057
00062
00064 #define AT45DIB_FDIRTY 0x0001
00065
00072 typedef struct _AT45DIB {
00077 sf_unit_t dib_page[2];
00078
00084 uint_fast8_t flags[2];
00085
00091 int dib_locks[2];
00092
00097 HANDLE dib_lque;
00098
00104 uint_fast8_t dib_pshft;
00105 } AT45DIB;
00106
00117 static int At45dibTransmitCmd(NUTSPINODE * node, uint8_t op, uint32_t parm, uint_fast8_t oplen)
00118 {
00119 uint8_t cmd[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
00120
00121 NUTASSERT(oplen <= sizeof(cmd));
00122
00123 cmd[0] = op;
00124 if (parm) {
00125 cmd[1] = (uint8_t) (parm >> 16);
00126 cmd[2] = (uint8_t) (parm >> 8);
00127 cmd[3] = (uint8_t) parm;
00128 }
00129 return (*((NUTSPIBUS *) node->node_bus)->bus_transfer) (node, cmd, NULL, oplen);
00130 }
00131
00145 static int At45dibTransfer(NUTSPINODE * node, uint8_t op, uint32_t parm, uint_fast8_t oplen,
00146 CONST void *txbuf, void *rxbuf, int xlen)
00147 {
00148 int rc;
00149 NUTSPIBUS *bus;
00150
00151
00152 NUTASSERT(node != NULL);
00153 bus = (NUTSPIBUS *) node->node_bus;
00154 NUTASSERT(bus != NULL);
00155 NUTASSERT(bus->bus_alloc != NULL);
00156 NUTASSERT(bus->bus_transfer != NULL);
00157 NUTASSERT(bus->bus_release != NULL);
00158
00159 rc = (*bus->bus_alloc) (node, 0);
00160 if (rc == 0) {
00161 rc = At45dibTransmitCmd(node, op, parm, oplen);
00162 if (rc == 0 && xlen) {
00163 rc = (*bus->bus_transfer) (node, txbuf, rxbuf, xlen);
00164 }
00165 (*bus->bus_release) (node);
00166 }
00167 return rc;
00168 }
00169
00180 static int At45dibCommand(NUTSPINODE * node, uint8_t op, uint32_t parm, uint_fast8_t oplen)
00181 {
00182 return At45dibTransfer(node, op, parm, oplen, NULL, NULL, 0);
00183 }
00184
00197 static int At45dibCompare(NUTSPINODE * node, uint8_t op, uint32_t parm, uint_fast8_t oplen, CONST void *buf, int xlen)
00198 {
00199 int rc;
00200 NUTSPIBUS *bus;
00201
00202
00203 NUTASSERT(node != NULL);
00204 bus = (NUTSPIBUS *) node->node_bus;
00205 NUTASSERT(bus != NULL);
00206 NUTASSERT(bus->bus_alloc != NULL);
00207 NUTASSERT(bus->bus_transfer != NULL);
00208 NUTASSERT(bus->bus_release != NULL);
00209
00210 rc = (*bus->bus_alloc) (node, 0);
00211 if (rc == 0) {
00212 rc = At45dibTransmitCmd(node, op, parm, oplen);
00213 if (rc == 0 && xlen) {
00214 int i;
00215 uint8_t c;
00216 uint8_t *cp = (uint8_t *) buf;
00217
00218 for (i = 0; i < xlen; i++) {
00219 rc = (*bus->bus_transfer) (node, NULL, &c, 1);
00220 if (rc) {
00221 break;
00222 }
00223 if (c != cp[i]) {
00224 rc = (int) c - (int) cp[i];
00225 break;
00226 }
00227 }
00228 }
00229 (*bus->bus_release) (node);
00230 }
00231 return rc;
00232 }
00233
00248 static int At45dibUsed(NUTSPINODE * node, uint8_t op, uint32_t parm, uint_fast8_t oplen, int xlen)
00249 {
00250 int rc;
00251 NUTSPIBUS *bus;
00252
00253
00254 NUTASSERT(node != NULL);
00255
00256 bus = (NUTSPIBUS *) node->node_bus;
00257 NUTASSERT(bus != NULL);
00258 NUTASSERT(bus->bus_alloc != NULL);
00259 NUTASSERT(bus->bus_transfer != NULL);
00260 NUTASSERT(bus->bus_release != NULL);
00261
00262 rc = (*bus->bus_alloc) (node, 0);
00263 if (rc == 0) {
00264 rc = At45dibTransmitCmd(node, op, parm, oplen);
00265 if (rc == 0 && xlen) {
00266 int i;
00267 int n = -1;
00268 uint8_t c;
00269
00270 for (i = 0; i < xlen; i++) {
00271 rc = (*bus->bus_transfer) (node, NULL, &c, 1);
00272 if (rc) {
00273 break;
00274 }
00275 if (c != 0xff) {
00276 n = i;
00277 }
00278 }
00279 if (rc == 0) {
00280 rc = n + 1;
00281 }
00282 }
00283 (*bus->bus_release) (node);
00284 }
00285 return rc;
00286 }
00287
00288
00289 #ifdef AT45D_CRC_PAGE
00290
00291
00292
00293
00294 static uint16_t crc_ccitt_update(uint16_t crc, uint8_t data)
00295 {
00296 data ^= (uint8_t) (crc);
00297 data ^= data << 4;
00298
00299 return ((((uint16_t) data << 8) | (crc >> 8)) ^ (uint8_t) (data >> 4) ^ ((uint16_t) data << 3));
00300 }
00301
00314 static int At45dibChecksum(NUTSPINODE * node, uint8_t op, uint32_t parm, uint_fast8_t oplen, uint16_t * crc16, int xlen)
00315 {
00316 int rc;
00317 NUTSPIBUS *bus;
00318
00319
00320 NUTASSERT(node != NULL);
00321 bus = (NUTSPIBUS *) node->node_bus;
00322 NUTASSERT(bus != NULL);
00323 NUTASSERT(bus->bus_alloc != NULL);
00324 NUTASSERT(bus->bus_transfer != NULL);
00325 NUTASSERT(bus->bus_release != NULL);
00326
00327 *crc16 = 0xffff;
00328 rc = (*bus->bus_alloc) (node, 0);
00329 if (rc == 0) {
00330 rc = At45dibTransmitCmd(node, op, parm, oplen);
00331 if (rc == 0 && xlen) {
00332 int i;
00333 uint8_t c;
00334 uint_fast8_t ne = 0;
00335
00336 for (i = 0; i < xlen; i++) {
00337 rc = (*bus->bus_transfer) (node, NULL, &c, 1);
00338 if (rc) {
00339 break;
00340 }
00341 if (ne || c != 0xff) {
00342 ne = 1;
00343 *crc16 = crc_ccitt_update(*crc16, c);
00344 }
00345 }
00346 if (*crc16 == 0) {
00347 *crc16 = 0xffff;
00348 }
00349 }
00350 (*bus->bus_release) (node);
00351 }
00352 return rc;
00353 }
00354
00355 #endif
00356
00357
00365 static uint8_t At45dibStatus(NUTSPINODE * node)
00366 {
00367 int rc;
00368 uint8_t cmd[2] = { DFCMD_READ_STATUS, 0xFF };
00369 NUTSPIBUS *bus;
00370
00371
00372 NUTASSERT(node != NULL);
00373 NUTASSERT(node->node_bus != NULL);
00374
00375 bus = (NUTSPIBUS *) node->node_bus;
00376 NUTASSERT(bus->bus_alloc != NULL);
00377 NUTASSERT(bus->bus_transfer != NULL);
00378 NUTASSERT(bus->bus_wait != NULL);
00379 NUTASSERT(bus->bus_release != NULL);
00380
00381 rc = (*bus->bus_alloc) (node, 0);
00382 if (rc == 0) {
00383 rc = (*bus->bus_transfer) (node, cmd, cmd, 2);
00384 if (rc == 0) {
00385 (*bus->bus_wait) (node, NUT_WAIT_INFINITE);
00386 rc = cmd[1];
00387 }
00388 (*bus->bus_release) (node);
00389 }
00390 return (uint8_t) rc;
00391 }
00392
00401 static int At45dibWaitReady(NUTSPINODE * node, uint32_t tmo)
00402 {
00403 uint8_t sr;
00404
00405 while (((sr = At45dibStatus(node)) & 0x80) == 0) {
00406 if (tmo-- == 0) {
00407 return -1;
00408 }
00409 }
00410 return 0;
00411 }
00412
00421 static int At45dibFlash(NUTSERIALFLASH * sfi, int_fast8_t b)
00422 {
00423 int rc;
00424 AT45DIB *at;
00425 uint32_t pga;
00426
00427 #ifdef AT45D_CRC_PAGE
00428
00429 {
00430 uint16_t crc16;
00431
00432 if (At45dibChecksum(sfi->sf_node, b ? DFCMD_BUF2_READ : DFCMD_BUF1_READ, 0, 5, &crc16, sfi->sf_unit_size)) {
00433 return -1;
00434 }
00435 if (At45dibTransfer
00436 (sfi->sf_node, b ? DFCMD_BUF2_WRITE : DFCMD_BUF1_WRITE, sfi->sf_unit_size, 4, &crc16, NULL, sizeof(crc16))) {
00437 return -1;
00438 }
00439 }
00440 #endif
00441
00442 at = (AT45DIB *) sfi->sf_info;
00443 pga = at->dib_page[b];
00444 pga <<= at->dib_pshft;
00445 rc = At45dibCommand(sfi->sf_node, b ? DFCMD_BUF2_FLASH_NE : DFCMD_BUF1_FLASH_NE, pga, 4);
00446 if (rc == 0) {
00447 rc = At45dibWaitReady(sfi->sf_node, AT45_WRITE_POLLS);
00448 at->flags[b] &= ~AT45DIB_FDIRTY;
00449 }
00450 return rc;
00451 }
00452
00459 static void At45dibRelease(NUTSERIALFLASH * sfi, int b)
00460 {
00461 AT45DIB *at = (AT45DIB *) sfi->sf_info;
00462
00463 at->dib_locks[b]--;
00464 NutEventPost(&at->dib_lque);
00465 }
00466
00475 static int_fast8_t At45dibAllocate(NUTSERIALFLASH * sfi, sf_unit_t pgn)
00476 {
00477 int_fast8_t b;
00478 AT45DIB *at;
00479
00480 at = (AT45DIB *) sfi->sf_info;
00481 for (;;) {
00482
00483
00484
00485 for (b = 0; b < 2; b++) {
00486 if (at->dib_page[b] == pgn) {
00487 at->dib_locks[b]++;
00488 at->flags[b] |= AT45DIB_FDIRTY;
00489 return b;
00490 }
00491 }
00492
00493
00494
00495
00496 for (b = 0; b < 2; b++) {
00497 if (at->dib_locks[b] == 0 && (at->flags[b] & AT45DIB_FDIRTY) == 0) {
00498 int rc;
00499 uint32_t pga = pgn;
00500
00501 pga <<= at->dib_pshft;
00502 at->dib_locks[b]++;
00503 if (b) {
00504 rc = At45dibCommand(sfi->sf_node, DFCMD_BUF2_LOAD_PAGE, pga, 4);
00505 } else {
00506 rc = At45dibCommand(sfi->sf_node, DFCMD_BUF1_LOAD_PAGE, pga, 4);
00507 }
00508 if (rc == 0) {
00509 rc = At45dibWaitReady(sfi->sf_node, AT45_WRITE_POLLS);
00510 }
00511 if (rc == 0) {
00512 at->dib_page[b] = pgn;
00513 at->flags[b] |= AT45DIB_FDIRTY;
00514
00515 return b;
00516 }
00517 At45dibRelease(sfi, b);
00518
00519 return -1;
00520 }
00521 }
00522
00523
00524
00525
00526 for (b = 0; b < 2; b++) {
00527 if (at->dib_locks[b] == 0 && (at->flags[b] & AT45DIB_FDIRTY) == AT45DIB_FDIRTY) {
00528 if (At45dibFlash(sfi, b)) {
00529 return -1;
00530 }
00531 break;
00532 }
00533 }
00534
00535
00536
00537
00538 if (b >= 2) {
00539 NutEventWait(&at->dib_lque, 0);
00540 }
00541 }
00542 }
00543
00551 static int SpiAt45dibInit(NUTSERIALFLASH * sfi)
00552 {
00553 int_fast8_t b;
00554 uint8_t sr;
00555 int_fast8_t i;
00556
00557
00558 NUTASSERT(sfi != NULL);
00559 NUTASSERT(sfi->sf_node != NULL);
00560
00561 sr = At45dibStatus(sfi->sf_node);
00562 sr &= AT45D_STATUS_DENSITY | AT45D_STATUS_PAGE_SIZE;
00563 for (i = at45d_known_types; --i >= 0;) {
00564 if (sr == at45d_info[i].at45d_srval) {
00565
00566 AT45DIB *at = calloc(1, sizeof(AT45DIB));
00567 if (at == NULL) {
00568 return -1;
00569 }
00570 at->dib_pshft = at45d_info[i].at45d_pshft;
00571 for (b = 0; b < 2; b++) {
00572 at->dib_page[b] = SERIALFLASH_MAX_UNITS;
00573 }
00574 sfi->sf_info = (void *) at;
00575 sfi->sf_units = (sf_unit_t) at45d_info[i].at45d_pages;
00576 sfi->sf_unit_size = at45d_info[i].at45d_psize;
00577 #ifdef AT45D_CRC_PAGE
00578 sfi->sf_unit_size -= 2;
00579 #endif
00580 return 0;
00581 }
00582 }
00583
00584 return -1;
00585 }
00586
00594 static void SpiAt45dibExit(NUTSERIALFLASH * sfi)
00595 {
00596 NUTASSERT(sfi != NULL);
00597 NUTASSERT(sfi->sf_info != NULL);
00598
00599 free(sfi->sf_info);
00600 }
00601
00611 static int SpiAt45dibCheck(NUTSERIALFLASH * sfi, sf_unit_t pgn, int cnt)
00612 {
00613 int rc = 0;
00614
00615 #ifdef AT45D_CRC_PAGE
00616 AT45DIB *at;
00617 int_fast8_t b;
00618 uint16_t crc16;
00619
00620
00621 NUTASSERT(sfi != NULL);
00622 NUTASSERT(sfi->sf_info != NULL);
00623 NUTASSERT(pgn + cnt <= sfi->sf_units);
00624 NUTASSERT(cnt >= 0);
00625
00626 at = (AT45DIB *) sfi->sf_info;
00627 while (cnt--) {
00628
00629 for (b = 0; b < 2 && at->dib_page[b] != pgn + cnt; b++);
00630 if (b < 2) {
00631 At45dibChecksum(sfi->sf_node, b ? DFCMD_BUF2_READ : DFCMD_BUF1_READ, 0, 5, &crc16, sfi->sf_unit_size + 2);
00632 }
00633
00634 else {
00635 uint32_t pga = pgn + cnt;
00636 pga <<= at->dib_pshft;
00637 At45dibChecksum(sfi->sf_node, DFCMD_READ_PAGE, pga, 8, &crc16, sfi->sf_unit_size + 2);
00638 }
00639 if (crc16 != 0xFFFF) {
00640 rc = -1;
00641 break;
00642 }
00643 }
00644 #endif
00645 return rc;
00646 }
00647
00660 static int SpiAt45dibRead(NUTSERIALFLASH * sfi, sf_unit_t pgn, int off, void *data, int len)
00661 {
00662 int rc = 0;
00663
00664
00665 NUTASSERT(sfi != NULL);
00666 NUTASSERT(sfi->sf_info != NULL);
00667 NUTASSERT(pgn < sfi->sf_units);
00668 NUTASSERT(off >= -(int) sfi->sf_unit_size && off <= (int) sfi->sf_unit_size);
00669 NUTASSERT(data != NULL);
00670 NUTASSERT(len >= 0 && len <= sfi->sf_unit_size);
00671
00672 if (len) {
00673 int_fast8_t b;
00674 AT45DIB *at = (AT45DIB *) sfi->sf_info;
00675
00676
00677 if (off < 0) {
00678 off += sfi->sf_unit_size;
00679 }
00680 NUTASSERT(off + len <= (int) sfi->sf_unit_size);
00681
00682
00683 for (b = 0; b < 2 && at->dib_page[b] != pgn; b++);
00684 if (b < 2) {
00685 rc = At45dibTransfer(sfi->sf_node, b ? DFCMD_BUF2_READ : DFCMD_BUF1_READ, off, 5, NULL, data, len);
00686 }
00687
00688 else {
00689 uint32_t pga = pgn;
00690
00691 pga <<= at->dib_pshft;
00692 pga |= off;
00693 rc = At45dibTransfer(sfi->sf_node, DFCMD_READ_PAGE, pga, 8, NULL, data, len);
00694 }
00695 }
00696 return rc;
00697 }
00698
00714 static int SpiAt45dibCompare(NUTSERIALFLASH * sfi, sf_unit_t pgn, int off, CONST void *data, int len)
00715 {
00716 int rc = 0;
00717
00718
00719 NUTASSERT(sfi != NULL);
00720 NUTASSERT(sfi->sf_info != NULL);
00721 NUTASSERT(pgn < sfi->sf_units);
00722 NUTASSERT(off >= -(int) sfi->sf_unit_size && off <= (int) sfi->sf_unit_size);
00723 NUTASSERT(data != NULL);
00724 NUTASSERT(len >= 0 && len <= sfi->sf_unit_size);
00725
00726 if (len) {
00727 int_fast8_t b;
00728 AT45DIB *at = (AT45DIB *) sfi->sf_info;
00729
00730
00731 if (off < 0) {
00732 off += sfi->sf_unit_size;
00733 }
00734 NUTASSERT(off + len <= (int) sfi->sf_unit_size);
00735
00736
00737 for (b = 0; b < 2 && at->dib_page[b] != pgn; b++);
00738 if (b < 2) {
00739 rc = At45dibCompare(sfi->sf_node, b ? DFCMD_BUF2_READ : DFCMD_BUF1_READ, off, 5, data, len);
00740 }
00741
00742 else {
00743 uint32_t pga = pgn;
00744
00745 pga <<= at->dib_pshft;
00746 pga |= off;
00747 rc = At45dibCompare(sfi->sf_node, DFCMD_READ_PAGE, pga, 8, data, len);
00748 }
00749 }
00750 return rc;
00751 }
00752
00766 static int SpiAt45dibUsed(NUTSERIALFLASH * sfi, sf_unit_t pgn, int skip)
00767 {
00768 int rc;
00769 int len;
00770 AT45DIB *at;
00771 int_fast8_t b;
00772
00773
00774 NUTASSERT(sfi != NULL);
00775 NUTASSERT(pgn < sfi->sf_units);
00776 NUTASSERT(skip <= (int) sfi->sf_unit_size);
00777
00778 at = (AT45DIB *) sfi->sf_info;
00779
00780
00781 len = (int) sfi->sf_unit_size;
00782 if (skip < 0) {
00783 len += skip;
00784 skip = 0;
00785 } else {
00786 len -= skip;
00787 }
00788
00789
00790 for (b = 0; b < 2 && at->dib_page[b] != pgn; b++);
00791 if (b < 2) {
00792 rc = At45dibUsed(sfi->sf_node, b ? DFCMD_BUF2_READ : DFCMD_BUF1_READ, skip, 5, len);
00793 }
00794
00795 else {
00796 uint32_t pga = pgn;
00797
00798 pga <<= at->dib_pshft;
00799 pga |= skip;
00800 rc = At45dibUsed(sfi->sf_node, DFCMD_READ_PAGE, pga, 8, len);
00801 }
00802 return rc;
00803 }
00804
00821 static int SpiAt45dibWrite(NUTSERIALFLASH * sfi, sf_unit_t pgn, int off, CONST void *data, int len)
00822 {
00823 int rc = 0;
00824
00825
00826 NUTASSERT(sfi != NULL);
00827 NUTASSERT(pgn < sfi->sf_units);
00828 NUTASSERT(off >= -(int) sfi->sf_unit_size && off <= (int) sfi->sf_unit_size);
00829 NUTASSERT(len == 0 || data != NULL);
00830 NUTASSERT(len >= 0 && len <= sfi->sf_unit_size);
00831
00832 if (len) {
00833 int_fast8_t b;
00834
00835
00836 if (off < 0) {
00837 off += sfi->sf_unit_size;
00838 }
00839 NUTASSERT(off + len <= (int) sfi->sf_unit_size);
00840
00841
00842 b = At45dibAllocate(sfi, pgn);
00843 if (b < 0) {
00844 return -1;
00845 }
00846
00847 rc = At45dibTransfer(sfi->sf_node, b ? DFCMD_BUF2_WRITE : DFCMD_BUF1_WRITE, off, 4, data, NULL, len);
00848 At45dibRelease(sfi, b);
00849 }
00850 return rc;
00851 }
00852
00866 static int SpiAt45dibCopy(NUTSERIALFLASH * sfi, sf_unit_t spg, sf_unit_t dpg)
00867 {
00868 int_fast8_t b;
00869
00870
00871 NUTASSERT(sfi != NULL);
00872 NUTASSERT(sfi->sf_info != NULL);
00873 NUTASSERT(spg < sfi->sf_units);
00874 NUTASSERT(dpg < sfi->sf_units);
00875
00876
00877 if (spg == dpg) {
00878 b = At45dibAllocate(sfi, spg);
00879 } else {
00880 AT45DIB *at = (AT45DIB *) sfi->sf_info;
00881
00882
00883 for (b = 0; b < 2; b++) {
00884 if (at->dib_page[b] == dpg) {
00885
00886 if (at->dib_locks[b]) {
00887 return -1;
00888 }
00889 at->dib_page[b] = SERIALFLASH_MAX_UNITS;
00890 }
00891 }
00892
00893 b = At45dibAllocate(sfi, spg);
00894 if (b >= 0) {
00895 at->dib_page[b] = dpg;
00896 }
00897 }
00898 if (b >= 0) {
00899 At45dibRelease(sfi, b);
00900 return 0;
00901 }
00902 return -1;
00903 }
00904
00917 static int SpiAt45dibCommit(NUTSERIALFLASH * sfi, sf_unit_t pgn)
00918 {
00919 int rc = 0;
00920 int_fast8_t b;
00921 AT45DIB *at;
00922
00923
00924 NUTASSERT(sfi != NULL);
00925 NUTASSERT(pgn < sfi->sf_units);
00926
00927 at = (AT45DIB *) sfi->sf_info;
00928 for (b = 0; b < 2 && at->dib_page[b] != pgn; b++);
00929 if (b < 2 && (at->flags[b] & AT45DIB_FDIRTY) == AT45DIB_FDIRTY) {
00930 rc = At45dibFlash(sfi, b);
00931 }
00932 return rc;
00933 }
00934
00944 static int SpiAt45dibErase(NUTSERIALFLASH * sfi, sf_unit_t pgn, int cnt)
00945 {
00946 int_fast8_t b;
00947 AT45DIB *at;
00948
00949
00950 NUTASSERT(sfi != NULL);
00951 NUTASSERT(pgn + cnt <= sfi->sf_units);
00952 NUTASSERT(cnt >= 0);
00953
00954 at = (AT45DIB *) sfi->sf_info;
00955
00956 for (b = 0; b < 2; b++) {
00957 if (at->dib_page[b] >= pgn && at->dib_page[b] < pgn + cnt) {
00958 at->dib_page[b] = SERIALFLASH_MAX_UNITS;
00959 at->flags[b] &= ~AT45DIB_FDIRTY;
00960 }
00961 }
00962 while (cnt--) {
00963 uint32_t pga = pgn + cnt;
00964
00965 pga <<= at->dib_pshft;
00966 if (At45dibCommand(sfi->sf_node, DFCMD_PAGE_ERASE, pga, 4)) {
00967 return -1;
00968 }
00969 if (At45dibWaitReady(sfi->sf_node, AT45_WRITE_POLLS)) {
00970 return -1;
00971 }
00972 }
00973 return 0;
00974 }
00975
00976 #ifndef SPI_RATE_AT45D0
00977 #define SPI_RATE_AT45D0 33000000
00978 #endif
00979
00980 #ifndef SPI_MODE_AT45D0
00981
00982 #ifdef SPI_CSHIGH_AT45D0
00983 #define SPI_MODE_AT45D0 (SPI_MODE_3 | SPI_MODE_CSHIGH)
00984 #else
00985 #define SPI_MODE_AT45D0 SPI_MODE_3
00986 #endif
00987
00988 #elif defined(SPI_CSHIGH_AT45D0)
00989
00990
00991
00992
00993
00994 #if SPI_MODE_AT45D0 == SPI_MODE_0
00995 #undef SPI_MODE_AT45D0
00996 #define SPI_MODE_AT45D0 (SPI_MODE_0 | SPI_MODE_CSHIGH)
00997 #elif SPI_MODE_AT45D0 == SPI_MODE_3
00998 #undef SPI_MODE_AT45D0
00999 #define SPI_MODE_AT45D0 (SPI_MODE_3 | SPI_MODE_CSHIGH)
01000 #endif
01001
01002 #endif
01003
01007 static NUTSPINODE spiNode0 = {
01008 NULL,
01009 NULL,
01010 SPI_RATE_AT45D0,
01011 SPI_MODE_AT45D0,
01012 8,
01013 0
01014 };
01015
01016 #ifndef MOUNT_OFFSET_AT45DIB0
01017 #ifdef MOUNT_OFFSET_AT45D0
01018 #define MOUNT_OFFSET_AT45DIB0 MOUNT_OFFSET_AT45D0
01019 #else
01020 #define MOUNT_OFFSET_AT45DIB0 0
01021 #endif
01022 #endif
01023
01024 #ifndef MOUNT_TOP_RESERVE_AT45DIB0
01025 #ifdef MOUNT_TOP_RESERVE_AT45D0
01026 #define MOUNT_TOP_RESERVE_AT45DIB0 MOUNT_TOP_RESERVE_AT45D0
01027 #else
01028 #define MOUNT_TOP_RESERVE_AT45DIB0 1
01029 #endif
01030 #endif
01031
01035 NUTSERIALFLASH flashAt45dib0 = {
01036 &spiNode0,
01037 NULL,
01038 0,
01039 0,
01040 MOUNT_OFFSET_AT45DIB0,
01041 MOUNT_TOP_RESERVE_AT45DIB0,
01042 SpiAt45dibInit,
01043 SpiAt45dibExit,
01044 SpiAt45dibCheck,
01045 SpiAt45dibRead,
01046 SpiAt45dibCompare,
01047 SpiAt45dibUsed,
01048 SpiAt45dibWrite,
01049 SpiAt45dibCopy,
01050 SpiAt45dibCommit,
01051 SpiAt45dibErase
01052 };
01053
01054 #ifndef SPI_RATE_AT45D1
01055 #define SPI_RATE_AT45D1 33000000
01056 #endif
01057
01058 #ifndef SPI_MODE_AT45D1
01059
01060 #ifdef SPI_CSHIGH_AT45D1
01061 #define SPI_MODE_AT45D1 (SPI_MODE_3 | SPI_MODE_CSHIGH)
01062 #else
01063 #define SPI_MODE_AT45D1 SPI_MODE_3
01064 #endif
01065
01066 #elif defined(SPI_CSHIGH_AT45D1)
01067
01068
01069 #if SPI_MODE_AT45D1 == SPI_MODE_0
01070 #undef SPI_MODE_AT45D1
01071 #define SPI_MODE_AT45D1 (SPI_MODE_0 | SPI_MODE_CSHIGH)
01072 #elif SPI_MODE_AT45D1 == SPI_MODE_3
01073 #undef SPI_MODE_AT45D1
01074 #define SPI_MODE_AT45D1 (SPI_MODE_3 | SPI_MODE_CSHIGH)
01075 #endif
01076
01077 #endif
01078
01082 static NUTSPINODE spiNode1 = {
01083 NULL,
01084 NULL,
01085 SPI_RATE_AT45D1,
01086 SPI_MODE_AT45D1,
01087 8,
01088 1
01089 };
01090
01091 #ifndef MOUNT_OFFSET_AT45DIB1
01092 #ifdef MOUNT_OFFSET_AT45D1
01093 #define MOUNT_OFFSET_AT45DIB1 MOUNT_OFFSET_AT45D1
01094 #else
01095 #define MOUNT_OFFSET_AT45DIB1 0
01096 #endif
01097 #endif
01098
01099 #ifndef MOUNT_TOP_RESERVE_AT45DIB1
01100 #ifdef MOUNT_TOP_RESERVE_AT45D1
01101 #define MOUNT_TOP_RESERVE_AT45DIB1 MOUNT_TOP_RESERVE_AT45D1
01102 #else
01103 #define MOUNT_TOP_RESERVE_AT45DIB1 1
01104 #endif
01105 #endif
01106
01110 NUTSERIALFLASH flashAt45dib1 = {
01111 &spiNode1,
01112 NULL,
01113 0,
01114 0,
01115 MOUNT_OFFSET_AT45DIB1,
01116 MOUNT_TOP_RESERVE_AT45DIB1,
01117 SpiAt45dibInit,
01118 SpiAt45dibExit,
01119 SpiAt45dibCheck,
01120 SpiAt45dibRead,
01121 SpiAt45dibCompare,
01122 SpiAt45dibUsed,
01123 SpiAt45dibWrite,
01124 SpiAt45dibCopy,
01125 SpiAt45dibCommit,
01126 SpiAt45dibErase
01127 };
01128