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
00068 #include <cfg/os.h>
00069 #include <cfg/memory.h>
00070
00071 #include <sys/timer.h>
00072
00073 #include <string.h>
00074 #include <stdlib.h>
00075
00076 #include <dev/at91_spi.h>
00077 #include <dev/at45db.h>
00078
00079 #ifndef MAX_AT45_DEVICES
00080 #define MAX_AT45_DEVICES 1
00081 #endif
00082
00083 #ifndef MAX_AT45_CMDLEN
00084 #define MAX_AT45_CMDLEN 8
00085 #endif
00086
00087 #ifndef AT45_CONF_DFSPI
00088 #define AT45_CONF_DFSPI SPI0_BASE
00089 #endif
00090
00091 #ifndef AT45_CONF_DFPCS
00092 #define AT45_CONF_DFPCS 1
00093 #endif
00094
00095 #ifndef AT45_ERASE_WAIT
00096 #define AT45_ERASE_WAIT 3000
00097 #endif
00098
00099 #ifndef AT45_CHIP_ERASE_WAIT
00100 #define AT45_CHIP_ERASE_WAIT 50000
00101 #endif
00102
00103 #ifndef AT45_WRITE_POLLS
00104 #define AT45_WRITE_POLLS 1000
00105 #endif
00106
00117 #define DFCMD_CONT_READ_LF 0x03
00118
00124 #define DFCMD_CONT_READ_HF 0x0B
00125
00127 #define DFCMD_BLOCK_ERASE 0x50
00128
00130 #define DFCMD_SECTOR_ERASE 0x7C
00131
00133 #define DFCMD_PAGE_ERASE 0x81
00134
00136 #define DFCMD_BUF1_PROG 0x82
00137
00139 #define DFCMD_BUF1_FLASH 0x83
00140
00142 #define DFCMD_BUF1_WRITE 0x84
00143
00145 #define DFCMD_BUF2_PROG 0x85
00146
00148 #define DFCMD_BUF2_FLASH 0x86
00149
00151 #define DFCMD_BUF2_WRITE 0x87
00152
00154 #define DFCMD_BUF1_FLASH_NE 0x88
00155
00157 #define DFCMD_BUF2_FLASH_NE 0x89
00158
00160 #define DFCMD_CHIP_ERASE 0xC7
00161
00163 #define DFCMD_BUF1_READ_LF 0xD1
00164
00169 #define DFCMD_READ_PAGE 0xD2
00170
00172 #define DFCMD_BUF2_READ_LF 0xD3
00173
00175 #define DFCMD_BUF1_READ 0xD4
00176
00178 #define DFCMD_BUF2_READ 0xD6
00179
00181 #define DFCMD_READ_STATUS 0xD7
00182
00188 #define DFCMD_CONT_READ 0xE8
00189
00191 #define AT45DB_AT91
00192
00193
00194 #if defined(AT45DB_SPI0_DEVICE)
00195
00196 #include <dev/sppif0.h>
00197 #if defined(AT45DB_RESET_ACTIVE_HIGH)
00198 #define SpiReset(act) Sppi0ChipReset(AT45DB_SPI0_DEVICE, act)
00199 #else
00200 #define SpiReset(act) Sppi0ChipReset(AT45DB_SPI0_DEVICE, !act)
00201 #endif
00202 #define SpiSetMode() Sppi0SetMode(AT45DB_SPI0_DEVICE, AT45DB_SPI_MODE)
00203 #define SpiSetSpeed() Sppi0SetSpeed(AT45DB_SPI0_DEVICE, AT45DB_SPI_RATE)
00204 #if defined(AT45DB_SELECT_ACTIVE_HIGH)
00205 #define SpiSelect() Sppi0SelectDevice(AT45DB_SPI0_DEVICE)
00206 #define SpiDeselect() Sppi0DeselectDevice(AT45DB_SPI0_DEVICE)
00207 #else
00208 #define SpiSelect() Sppi0NegSelectDevice(AT45DB_SPI0_DEVICE)
00209 #define SpiDeselect() Sppi0NegDeselectDevice(AT45DB_SPI0_DEVICE)
00210 #endif
00211 #define SpiByte Sppi0Byte
00212
00213 #elif defined(AT45DB_SBBI0_DEVICE)
00214
00215 #include <dev/sbbif0.h>
00216 #if defined(VS10XX_RESET_ACTIVE_HIGH)
00217 #define SpiReset(act) Sbbi0ChipReset(AT45DB_SBBI0_DEVICE, act)
00218 #else
00219 #define SpiReset(act) Sbbi0ChipReset(AT45DB_SBBI0_DEVICE, !act)
00220 #endif
00221 #define SpiSetMode() Sbbi0SetMode(AT45DB_SBBI0_DEVICE, AT45DB_SPI_MODE)
00222 #define SpiSetSpeed() Sbbi0SetSpeed(AT45DB_SBBI0_DEVICE, AT45DB_SPI_RATE)
00223 #if defined(VS10XX_SELECT_ACTIVE_HIGH)
00224 #define SpiSelect() Sbbi0SelectDevice(AT45DB_SBBI0_DEVICE)
00225 #define SpiDeselect() Sbbi0DeselectDevice(AT45DB_SBBI0_DEVICE)
00226 #else
00227 #define SpiSelect() Sbbi0NegSelectDevice(AT45DB_SBBI0_DEVICE)
00228 #define SpiDeselect() Sbbi0NegDeselectDevice(AT45DB_SBBI0_DEVICE)
00229 #endif
00230 #define SpiByte Sbbi0Byte
00231
00232 #endif
00233
00237 typedef struct _AT45_DEVTAB {
00238 uint32_t devt_pages;
00239 u_int devt_pagsiz;
00240 u_int devt_offs;
00241 uint8_t devt_srmsk;
00242 uint8_t devt_srval;
00243 } AT45_DEVTAB;
00244
00248 typedef struct _AT45DB_DCB {
00249 AT45_DEVTAB *dcb_devt;
00250 u_int dcb_spibas;
00251 u_int dcb_spipcs;
00252 uint8_t dcb_cmdbuf[MAX_AT45_CMDLEN];
00253 } AT45DB_DCB;
00254
00258 AT45_DEVTAB at45_devt[] = {
00259 {512, 264, 9, 0x3C, 0x0C},
00260 {1025, 264, 9, 0x3C, 0x14},
00261 {2048, 264, 9, 0x3C, 0x1C},
00262 {4096, 264, 9, 0x3C, 0x24},
00263 {4096, 528, 10, 0x3C, 0x2C},
00264 {8192, 528, 10, 0x3C, 0x34},
00265 {8192, 1056, 11, 0x38, 0x38},
00266 {0, 0, 0, 0, 0}
00267 };
00268
00272 static AT45DB_DCB dcbtab[MAX_AT45_DEVICES];
00273
00274
00275 static uint_least8_t dcbnum;
00276
00277
00278 static int dd_param = -1;
00279
00291 int At45dbSendCmd(int dd, uint8_t op, uint32_t parm, int len, CONST void *tdata, void *rdata, int datalen)
00292 {
00293 uint8_t *cb = dcbtab[dd].dcb_cmdbuf;
00294
00295 if (len > MAX_AT45_CMDLEN) {
00296 return -1;
00297 }
00298 memset(cb, 0, len);
00299 cb[0] = op;
00300 if (parm) {
00301 cb[1] = (uint8_t) (parm >> 16);
00302 cb[2] = (uint8_t) (parm >> 8);
00303 cb[3] = (uint8_t) parm;
00304 }
00305 return At91SpiTransfer2(dcbtab[dd].dcb_spibas, dcbtab[dd].dcb_spipcs, cb, cb, len, tdata, rdata, datalen);
00306 }
00307
00308 uint8_t At45dbGetStatus(int dd)
00309 {
00310 uint8_t buf[2] = { DFCMD_READ_STATUS, 0xFF };
00311
00312 if (At91SpiTransfer2(dcbtab[dd].dcb_spibas, dcbtab[dd].dcb_spipcs, buf, buf, 2, NULL, NULL, 0)) {
00313 return (uint8_t) - 1;
00314 }
00315 return buf[1];
00316 }
00317
00323 int At45dbWaitReady(int dd, uint32_t tmo, int poll)
00324 {
00325 uint8_t sr;
00326
00327 while (((sr = At45dbGetStatus(dd)) & 0x80) == 0) {
00328 if (!poll) {
00329 NutSleep(1);
00330 }
00331 if (tmo-- == 0) {
00332 return -1;
00333 }
00334 }
00335 return 0;
00336 }
00337
00347 int At45dbInit(u_int spibas, u_int spipcs)
00348 {
00349 int dd = -1;
00350 uint8_t sr;
00351 uint_fast8_t i;
00352
00353 for (i = 0; i < dcbnum; i++) {
00354 if (dcbtab[i].dcb_spibas == spibas && dcbtab[i].dcb_spipcs == spipcs) {
00355 return i;
00356 }
00357 }
00358
00359 if (dcbnum >= MAX_AT45_DEVICES) {
00360 return -1;
00361 }
00362
00363 #if defined(MCU_AT91SAM7X256) || defined(MCU_AT91SAM9260) || defined(MCU_AT91SAM9XE512)
00364 At91SpiInit(spibas);
00365 At91SpiReset(spibas);
00366 At91SpiInitChipSelects(spibas, _BV(spipcs));
00367 At91SpiSetRate(spibas, spipcs, 1000000);
00368 At91SpiSetModeFlags(spibas, spipcs, SPIMF_MASTER | SPIMF_SCKIAHI | SPIMF_CAPRISE);
00369 #elif defined(MCU_AT91R40008)
00370 #endif
00371
00372 dcbtab[dcbnum].dcb_spibas = spibas;
00373 dcbtab[dcbnum].dcb_spipcs = spipcs;
00374 sr = At45dbGetStatus(dcbnum);
00375
00376 for (i = 0; at45_devt[i].devt_pages; i++) {
00377 if ((sr & at45_devt[i].devt_srmsk) == at45_devt[i].devt_srval) {
00378 dcbtab[dcbnum].dcb_devt = &at45_devt[i];
00379 dd = dcbnum++;
00380 break;
00381 }
00382 }
00383 return dd;
00384 }
00385
00389 int At45dbPageErase(int dd, uint32_t pgn)
00390 {
00391 pgn <<= dcbtab[dd].dcb_devt->devt_offs;
00392 return At45dbSendCmd(dd, DFCMD_PAGE_ERASE, pgn, 4, NULL, NULL, 0);
00393 }
00394
00398 int At45dbChipErase(void)
00399 {
00400 return -1;
00401 }
00402
00413 int At45dbPageRead(int dd, uint32_t pgn, void *data, u_int len)
00414 {
00415 pgn <<= dcbtab[dd].dcb_devt->devt_offs;
00416 return At45dbSendCmd(dd, DFCMD_CONT_READ, pgn, 8, data, data, len);
00417 }
00418
00431 int At45dbPageWrite(int dd, uint32_t pgn, CONST void *data, u_int len)
00432 {
00433 int rc = -1;
00434 void *rp;
00435
00436 if ((rp = malloc(len)) != NULL) {
00437
00438 if (At45dbSendCmd(dd, DFCMD_BUF1_WRITE, 0, 4, data, rp, len) == 0) {
00439
00440 pgn <<= dcbtab[dd].dcb_devt->devt_offs;
00441 if (At45dbSendCmd(dd, DFCMD_BUF1_FLASH, pgn, 4, NULL, NULL, 0) == 0) {
00442 rc = At45dbWaitReady(dd, AT45_WRITE_POLLS, 1);
00443 }
00444 }
00445 free(rp);
00446 }
00447 return rc;
00448 }
00449
00450 uint32_t At45dbPages(int dd)
00451 {
00452 return dcbtab[dd].dcb_devt->devt_pages;
00453 }
00454
00455 u_int At45dbPageSize(int dd)
00456 {
00457 return dcbtab[dd].dcb_devt->devt_pagsiz;
00458 }
00459
00460 uint32_t At45dbParamPage(void)
00461 {
00462 #ifdef AT45_CONF_PAGE
00463 return AT45_CONF_PAGE;
00464 #else
00465 return dcbtab[dd_param].dcb_devt->devt_pages - 1;
00466 #endif
00467 }
00468
00480 int At45dbParamSize(void)
00481 {
00482 int rc;
00483
00484 if (dd_param == -1 && (dd_param = At45dbInit(AT45_CONF_DFSPI, AT45_CONF_DFPCS)) == -1) {
00485 return -1;
00486 }
00487 #ifdef AT45_CONF_SIZE
00488 rc = AT45_CONF_SIZE;
00489 #else
00490 rc = dcbtab[dd_param].dcb_devt->devt_pagsiz;
00491 #endif
00492 return rc;
00493 }
00494
00504 int At45dbParamRead(u_int pos, void *data, u_int len)
00505 {
00506 int rc = -1;
00507 uint8_t *buff;
00508 int csize = At45dbParamSize();
00509 uint32_t cpage = At45dbParamPage();
00510
00511
00512 if (csize > len && (buff = malloc(csize)) != NULL) {
00513 rc = At45dbPageRead(dd_param, cpage, buff, csize);
00514
00515 memcpy(data, buff + pos, len);
00516 free(buff);
00517 }
00518 return rc;
00519 }
00520
00530 int At45dbParamWrite(u_int pos, CONST void *data, u_int len)
00531 {
00532 int rc = -1;
00533 uint8_t *buff;
00534 int csize = At45dbParamSize();
00535 uint32_t cpage = At45dbParamPage();
00536
00537
00538 if (csize > len && (buff = malloc(csize)) != NULL) {
00539 rc = At45dbPageRead(dd_param, cpage, buff, csize);
00540
00541 if (memcmp(buff + pos, data, len)) {
00542
00543 memcpy(buff + pos, data, len);
00544
00545 rc = At45dbPageWrite(dd_param, cpage, buff, csize);
00546 }
00547 free(buff);
00548 }
00549 return rc;
00550 }