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
00078 #include <cfg/os.h>
00079 #include <cfg/memory.h>
00080
00081 #include <sys/timer.h>
00082
00083 #include <string.h>
00084 #include <stdlib.h>
00085
00086 #include <dev/at91_spi.h>
00087 #include <dev/at45db.h>
00088
00089 #ifndef MAX_AT45_DEVICES
00090 #define MAX_AT45_DEVICES 1
00091 #endif
00092
00093 #ifndef MAX_AT45_CMDLEN
00094 #define MAX_AT45_CMDLEN 8
00095 #endif
00096
00097 #ifndef AT45_CONF_DFSPI
00098 #define AT45_CONF_DFSPI SPI0_BASE
00099 #endif
00100
00101 #ifndef AT45_CONF_DFPCS
00102 #define AT45_CONF_DFPCS 1
00103 #endif
00104
00105 #ifndef AT45_ERASE_WAIT
00106 #define AT45_ERASE_WAIT 3000
00107 #endif
00108
00109 #ifndef AT45_CHIP_ERASE_WAIT
00110 #define AT45_CHIP_ERASE_WAIT 50000
00111 #endif
00112
00113 #ifndef AT45_WRITE_POLLS
00114 #define AT45_WRITE_POLLS 1000
00115 #endif
00116
00127 #define DFCMD_CONT_READ_LF 0x03
00128
00134 #define DFCMD_CONT_READ_HF 0x0B
00135
00137 #define DFCMD_BLOCK_ERASE 0x50
00138
00140 #define DFCMD_SECTOR_ERASE 0x7C
00141
00143 #define DFCMD_PAGE_ERASE 0x81
00144
00146 #define DFCMD_BUF1_PROG 0x82
00147
00149 #define DFCMD_BUF1_FLASH 0x83
00150
00152 #define DFCMD_BUF1_WRITE 0x84
00153
00155 #define DFCMD_BUF2_PROG 0x85
00156
00158 #define DFCMD_BUF2_FLASH 0x86
00159
00161 #define DFCMD_BUF2_WRITE 0x87
00162
00164 #define DFCMD_BUF1_FLASH_NE 0x88
00165
00167 #define DFCMD_BUF2_FLASH_NE 0x89
00168
00170 #define DFCMD_CHIP_ERASE 0xC7
00171
00173 #define DFCMD_BUF1_READ_LF 0xD1
00174
00179 #define DFCMD_READ_PAGE 0xD2
00180
00182 #define DFCMD_BUF2_READ_LF 0xD3
00183
00185 #define DFCMD_BUF1_READ 0xD4
00186
00188 #define DFCMD_BUF2_READ 0xD6
00189
00191 #define DFCMD_READ_STATUS 0xD7
00192
00198 #define DFCMD_CONT_READ 0xE8
00199
00201 #define AT45DB_AT91
00202
00203
00204 #if defined(AT45DB_SPI0_DEVICE)
00205
00206 #include <dev/sppif0.h>
00207 #if defined(AT45DB_RESET_ACTIVE_HIGH)
00208 #define SpiReset(act) Sppi0ChipReset(AT45DB_SPI0_DEVICE, act)
00209 #else
00210 #define SpiReset(act) Sppi0ChipReset(AT45DB_SPI0_DEVICE, !act)
00211 #endif
00212 #define SpiSetMode() Sppi0SetMode(AT45DB_SPI0_DEVICE, AT45DB_SPI_MODE)
00213 #define SpiSetSpeed() Sppi0SetSpeed(AT45DB_SPI0_DEVICE, AT45DB_SPI_RATE)
00214 #if defined(AT45DB_SELECT_ACTIVE_HIGH)
00215 #define SpiSelect() Sppi0SelectDevice(AT45DB_SPI0_DEVICE)
00216 #define SpiDeselect() Sppi0DeselectDevice(AT45DB_SPI0_DEVICE)
00217 #else
00218 #define SpiSelect() Sppi0NegSelectDevice(AT45DB_SPI0_DEVICE)
00219 #define SpiDeselect() Sppi0NegDeselectDevice(AT45DB_SPI0_DEVICE)
00220 #endif
00221 #define SpiByte Sppi0Byte
00222
00223 #elif defined(AT45DB_SBBI0_DEVICE)
00224
00225 #include <dev/sbbif0.h>
00226 #if defined(AT45DB_RESET_ACTIVE_HIGH)
00227 #define SpiReset(act) Sbbi0ChipReset(AT45DB_SBBI0_DEVICE, act)
00228 #else
00229 #define SpiReset(act) Sbbi0ChipReset(AT45DB_SBBI0_DEVICE, !act)
00230 #endif
00231 #define SpiSetMode() Sbbi0SetMode(AT45DB_SBBI0_DEVICE, AT45DB_SPI_MODE)
00232 #define SpiSetSpeed() Sbbi0SetSpeed(AT45DB_SBBI0_DEVICE, AT45DB_SPI_RATE)
00233 #if defined(AT45DB_SELECT_ACTIVE_HIGH)
00234 #define SpiSelect() Sbbi0SelectDevice(AT45DB_SBBI0_DEVICE)
00235 #define SpiDeselect() Sbbi0DeselectDevice(AT45DB_SBBI0_DEVICE)
00236 #else
00237 #define SpiSelect() Sbbi0NegSelectDevice(AT45DB_SBBI0_DEVICE)
00238 #define SpiDeselect() Sbbi0NegDeselectDevice(AT45DB_SBBI0_DEVICE)
00239 #endif
00240 #define SpiByte Sbbi0Byte
00241
00242 #endif
00243
00247 typedef struct _AT45_DEVTAB {
00248 uint32_t devt_pages;
00249 unsigned int devt_pagsiz;
00250 unsigned int devt_offs;
00251 uint8_t devt_srmsk;
00252 uint8_t devt_srval;
00253 } AT45_DEVTAB;
00254
00258 typedef struct _AT45DB_DCB {
00259 AT45_DEVTAB *dcb_devt;
00260 unsigned int dcb_spibas;
00261 unsigned int dcb_spipcs;
00262 uint8_t dcb_cmdbuf[MAX_AT45_CMDLEN];
00263 } AT45DB_DCB;
00264
00268 AT45_DEVTAB at45_devt[] = {
00269 {512, 264, 9, 0x3C, 0x0C},
00270 {1025, 264, 9, 0x3C, 0x14},
00271 {2048, 264, 9, 0x3C, 0x1C},
00272 {4096, 264, 9, 0x3C, 0x24},
00273 {4096, 528, 10, 0x3C, 0x2C},
00274 {8192, 528, 10, 0x3C, 0x34},
00275 {8192, 1056, 11, 0x38, 0x38},
00276 {0, 0, 0, 0, 0}
00277 };
00278
00282 static AT45DB_DCB dcbtab[MAX_AT45_DEVICES];
00283
00284
00285 static uint_least8_t dcbnum;
00286
00287
00288 static int dd_param = -1;
00289
00301 int At45dbSendCmd(int dd, uint8_t op, uint32_t parm, int len, CONST void *tdata, void *rdata, int datalen)
00302 {
00303 uint8_t *cb = dcbtab[dd].dcb_cmdbuf;
00304
00305 if (len > MAX_AT45_CMDLEN) {
00306 return -1;
00307 }
00308 memset(cb, 0, len);
00309 cb[0] = op;
00310 if (parm) {
00311 cb[1] = (uint8_t) (parm >> 16);
00312 cb[2] = (uint8_t) (parm >> 8);
00313 cb[3] = (uint8_t) parm;
00314 }
00315 return At91SpiTransfer2(dcbtab[dd].dcb_spibas, dcbtab[dd].dcb_spipcs, cb, cb, len, tdata, rdata, datalen);
00316 }
00317
00318 uint8_t At45dbGetStatus(int dd)
00319 {
00320 uint8_t buf[2] = { DFCMD_READ_STATUS, 0xFF };
00321
00322 if (At91SpiTransfer2(dcbtab[dd].dcb_spibas, dcbtab[dd].dcb_spipcs, buf, buf, 2, NULL, NULL, 0)) {
00323 return (uint8_t) - 1;
00324 }
00325 return buf[1];
00326 }
00327
00333 int At45dbWaitReady(int dd, uint32_t tmo, int poll)
00334 {
00335 uint8_t sr;
00336
00337 while (((sr = At45dbGetStatus(dd)) & 0x80) == 0) {
00338 if (!poll) {
00339 NutSleep(1);
00340 }
00341 if (tmo-- == 0) {
00342 return -1;
00343 }
00344 }
00345 return 0;
00346 }
00347
00357 int At45dbInit(unsigned int spibas, unsigned int spipcs)
00358 {
00359 int dd = -1;
00360 uint8_t sr;
00361 uint_fast8_t i;
00362
00363 for (i = 0; i < dcbnum; i++) {
00364 if (dcbtab[i].dcb_spibas == spibas && dcbtab[i].dcb_spipcs == spipcs) {
00365 return i;
00366 }
00367 }
00368
00369 if (dcbnum >= MAX_AT45_DEVICES) {
00370 return -1;
00371 }
00372
00373 #if defined(MCU_AT91SAM7X) || defined(MCU_AT91SAM7SE) || defined(MCU_AT91SAM9260) || defined(MCU_AT91SAM9XE)
00374 At91SpiInit(spibas);
00375 At91SpiReset(spibas);
00376 At91SpiInitChipSelects(spibas, _BV(spipcs));
00377 At91SpiSetRate(spibas, spipcs, 1000000);
00378 At91SpiSetModeFlags(spibas, spipcs, SPIMF_MASTER | SPIMF_SCKIAHI | SPIMF_CAPRISE);
00379 #elif defined(MCU_AT91R40008)
00380 #endif
00381
00382 dcbtab[dcbnum].dcb_spibas = spibas;
00383 dcbtab[dcbnum].dcb_spipcs = spipcs;
00384 sr = At45dbGetStatus(dcbnum);
00385
00386 for (i = 0; at45_devt[i].devt_pages; i++) {
00387 if ((sr & at45_devt[i].devt_srmsk) == at45_devt[i].devt_srval) {
00388 dcbtab[dcbnum].dcb_devt = &at45_devt[i];
00389 dd = dcbnum++;
00390 break;
00391 }
00392 }
00393 return dd;
00394 }
00395
00399 int At45dbPageErase(int dd, uint32_t pgn)
00400 {
00401 pgn <<= dcbtab[dd].dcb_devt->devt_offs;
00402 return At45dbSendCmd(dd, DFCMD_PAGE_ERASE, pgn, 4, NULL, NULL, 0);
00403 }
00404
00408 int At45dbChipErase(void)
00409 {
00410 return -1;
00411 }
00412
00423 int At45dbPageRead(int dd, uint32_t pgn, void *data, unsigned int len)
00424 {
00425 pgn <<= dcbtab[dd].dcb_devt->devt_offs;
00426 return At45dbSendCmd(dd, DFCMD_CONT_READ, pgn, 8, data, data, len);
00427 }
00428
00441 int At45dbPageWrite(int dd, uint32_t pgn, CONST void *data, unsigned int len)
00442 {
00443 int rc = -1;
00444 void *rp;
00445
00446 if ((rp = malloc(len)) != NULL) {
00447
00448 if (At45dbSendCmd(dd, DFCMD_BUF1_WRITE, 0, 4, data, rp, len) == 0) {
00449
00450 pgn <<= dcbtab[dd].dcb_devt->devt_offs;
00451 if (At45dbSendCmd(dd, DFCMD_BUF1_FLASH, pgn, 4, NULL, NULL, 0) == 0) {
00452 rc = At45dbWaitReady(dd, AT45_WRITE_POLLS, 1);
00453 }
00454 }
00455 free(rp);
00456 }
00457 return rc;
00458 }
00459
00460 uint32_t At45dbPages(int dd)
00461 {
00462 return dcbtab[dd].dcb_devt->devt_pages;
00463 }
00464
00465 unsigned int At45dbPageSize(int dd)
00466 {
00467 return dcbtab[dd].dcb_devt->devt_pagsiz;
00468 }
00469
00470 uint32_t At45dbParamPage(void)
00471 {
00472 #ifdef AT45_CONF_PAGE
00473 return AT45_CONF_PAGE;
00474 #else
00475 return dcbtab[dd_param].dcb_devt->devt_pages - 1;
00476 #endif
00477 }
00478
00490 int At45dbParamSize(void)
00491 {
00492 int rc;
00493
00494 if (dd_param == -1 && (dd_param = At45dbInit(AT45_CONF_DFSPI, AT45_CONF_DFPCS)) == -1) {
00495 return -1;
00496 }
00497 #ifdef AT45_CONF_SIZE
00498 rc = AT45_CONF_SIZE;
00499 #else
00500 rc = dcbtab[dd_param].dcb_devt->devt_pagsiz;
00501 #endif
00502 return rc;
00503 }
00504
00514 int At45dbParamRead(unsigned int pos, void *data, unsigned int len)
00515 {
00516 int rc = -1;
00517 uint8_t *buff;
00518 int csize = At45dbParamSize();
00519 uint32_t cpage = At45dbParamPage();
00520
00521
00522 if (csize > len && (buff = malloc(csize)) != NULL) {
00523 rc = At45dbPageRead(dd_param, cpage, buff, csize);
00524
00525 memcpy(data, buff + pos, len);
00526 free(buff);
00527 }
00528 return rc;
00529 }
00530
00540 int At45dbParamWrite(unsigned int pos, CONST void *data, unsigned int len)
00541 {
00542 int rc = -1;
00543 uint8_t *buff;
00544 int csize = At45dbParamSize();
00545 uint32_t cpage = At45dbParamPage();
00546
00547
00548 if (csize > len && (buff = malloc(csize)) != NULL) {
00549 rc = At45dbPageRead(dd_param, cpage, buff, csize);
00550
00551 if (memcmp(buff + pos, data, len)) {
00552
00553 memcpy(buff + pos, data, len);
00554
00555 rc = At45dbPageWrite(dd_param, cpage, buff, csize);
00556 }
00557 free(buff);
00558 }
00559 return rc;
00560 }