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