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 <dev/blockdev.h>
00047 #include <sys/nutdebug.h>
00048 #include <sys/timer.h>
00049
00050 #include <stdlib.h>
00051 #include <string.h>
00052
00053 #include <dev/spi_node_at45d.h>
00054
00059
00060 typedef struct _AT45D_DCB {
00061 HANDLE dcb_lock;
00062 } AT45D_DCB;
00063
00064 static AT45D_DCB dcbAt45d0 = {
00065 SIGNALED
00066 };
00067
00068 static AT45D_DCB dcbAt45d1 = {
00069 SIGNALED
00070 };
00071
00072 static AT45D_DCB dcbAt45d2 = {
00073 SIGNALED
00074 };
00075
00076 static AT45D_DCB dcbAt45d3 = {
00077 SIGNALED
00078 };
00079
00080 int At45dNodeLock(NUTSPINODE * node)
00081 {
00082 AT45D_DCB *dcb = (AT45D_DCB *) node->node_dcb;
00083
00084 return NutEventWait(&dcb->dcb_lock, NUT_WAIT_INFINITE);
00085 }
00086
00087 void At45dNodeUnlock(NUTSPINODE * node)
00088 {
00089 AT45D_DCB *dcb = (AT45D_DCB *) node->node_dcb;
00090
00091 NutEventPost(&dcb->dcb_lock);
00092 }
00093
00104 static int At45dNodeTransmitCmd(NUTSPINODE * node, uint8_t op, uint32_t parm, uint_fast8_t oplen)
00105 {
00106 uint8_t cmd[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
00107
00108 NUTASSERT(oplen <= sizeof(cmd));
00109
00110 cmd[0] = op;
00111 if (parm) {
00112 cmd[1] = (uint8_t) (parm >> 16);
00113 cmd[2] = (uint8_t) (parm >> 8);
00114 cmd[3] = (uint8_t) parm;
00115 }
00116 return (*((NUTSPIBUS *) node->node_bus)->bus_transfer) (node, cmd, NULL, oplen);
00117 }
00118
00132 int At45dNodeTransfer(NUTSPINODE * node, uint8_t op, uint32_t parm, uint_fast8_t oplen,
00133 CONST void *txbuf, void *rxbuf, int xlen)
00134 {
00135 int rc;
00136 NUTSPIBUS *bus;
00137
00138
00139 NUTASSERT(node != NULL);
00140 bus = (NUTSPIBUS *) node->node_bus;
00141 NUTASSERT(bus != NULL);
00142 NUTASSERT(bus->bus_alloc != NULL);
00143 NUTASSERT(bus->bus_transfer != NULL);
00144 NUTASSERT(bus->bus_release != NULL);
00145
00146 rc = (*bus->bus_alloc) (node, 0);
00147 if (rc == 0) {
00148 rc = At45dNodeTransmitCmd(node, op, parm, oplen);
00149 if (rc == 0 && xlen) {
00150 rc = (*bus->bus_transfer) (node, txbuf, rxbuf, xlen);
00151 }
00152 (*bus->bus_release) (node);
00153 }
00154 return rc;
00155 }
00156
00167 int At45dNodeCommand(NUTSPINODE * node, uint8_t op, uint32_t parm, uint_fast8_t oplen)
00168 {
00169 return At45dNodeTransfer(node, op, parm, oplen, NULL, NULL, 0);
00170 }
00171
00179 uint8_t At45dNodeStatus(NUTSPINODE * node)
00180 {
00181 int rc;
00182 uint8_t cmd[2] = { DFCMD_READ_STATUS, 0xFF };
00183 NUTSPIBUS *bus;
00184
00185
00186 NUTASSERT(node != NULL);
00187 NUTASSERT(node->node_bus != NULL);
00188
00189 bus = (NUTSPIBUS *) node->node_bus;
00190 NUTASSERT(bus->bus_alloc != NULL);
00191 NUTASSERT(bus->bus_transfer != NULL);
00192 NUTASSERT(bus->bus_wait != NULL);
00193 NUTASSERT(bus->bus_release != NULL);
00194
00195 rc = (*bus->bus_alloc) (node, 0);
00196 if (rc == 0) {
00197 rc = (*bus->bus_transfer) (node, cmd, cmd, 2);
00198 if (rc == 0) {
00199 (*bus->bus_wait) (node, NUT_WAIT_INFINITE);
00200 rc = cmd[1];
00201 }
00202 (*bus->bus_release) (node);
00203 }
00204 return (uint8_t) rc;
00205 }
00206
00219 int At45dNodeWaitReady(NUTSPINODE * node, uint32_t tmo, int poll)
00220 {
00221 uint8_t sr;
00222
00223 while (((sr = At45dNodeStatus(node)) & 0x80) == 0) {
00224 if (!poll) {
00225 NutSleep(1);
00226 }
00227 if (tmo-- == 0) {
00228 return -1;
00229 }
00230 }
00231 return 0;
00232 }
00233
00247 AT45D_INFO *At45dNodeProbe(NUTSPINODE * node)
00248 {
00249 int_fast8_t i;
00250 uint8_t sr;
00251
00252 if (At45dNodeWaitReady(node, 10, 1) == 0) {
00253 sr = At45dNodeStatus(node);
00254 if (sr != 0xff) {
00255 sr &= AT45D_STATUS_DENSITY | AT45D_STATUS_PAGE_SIZE;
00256 for (i = at45d_known_types; --i >= 0;) {
00257 if (sr == at45d_info[i].at45d_srval) {
00258 return &at45d_info[i];
00259 }
00260 }
00261 }
00262 }
00263 return NULL;
00264 }
00265
00266 #ifndef SPI_RATE_AT45D0
00267 #define SPI_RATE_AT45D0 33000000
00268 #endif
00269
00270 #ifndef SPI_MODE_AT45D0
00271
00272 #ifdef SPI_CSHIGH_AT45D0
00273 #define SPI_MODE_AT45D0 (SPI_MODE_3 | SPI_MODE_CSHIGH)
00274 #else
00275 #define SPI_MODE_AT45D0 SPI_MODE_3
00276 #endif
00277
00278 #elif defined(SPI_CSHIGH_AT45D0)
00279
00280
00281
00282
00283
00284 #if SPI_MODE_AT45D0 == SPI_MODE_0
00285 #undef SPI_MODE_AT45D0
00286 #define SPI_MODE_AT45D0 (SPI_MODE_0 | SPI_MODE_CSHIGH)
00287 #elif SPI_MODE_AT45D0 == SPI_MODE_3
00288 #undef SPI_MODE_AT45D0
00289 #define SPI_MODE_AT45D0 (SPI_MODE_3 | SPI_MODE_CSHIGH)
00290 #endif
00291
00292 #endif
00293
00297 NUTSPINODE nodeAt45d0 = {
00298 NULL,
00299 NULL,
00300 SPI_RATE_AT45D0,
00301 SPI_MODE_AT45D0,
00302 8,
00303 0,
00304 &dcbAt45d0
00305 };
00306
00307 #ifndef SPI_RATE_AT45D1
00308 #define SPI_RATE_AT45D1 33000000
00309 #endif
00310
00311 #ifndef SPI_MODE_AT45D1
00312
00313 #ifdef SPI_CSHIGH_AT45D1
00314 #define SPI_MODE_AT45D1 (SPI_MODE_3 | SPI_MODE_CSHIGH)
00315 #else
00316 #define SPI_MODE_AT45D1 SPI_MODE_3
00317 #endif
00318
00319 #elif defined(SPI_CSHIGH_AT45D1)
00320
00321
00322 #if SPI_MODE_AT45D1 == SPI_MODE_0
00323 #undef SPI_MODE_AT45D1
00324 #define SPI_MODE_AT45D1 (SPI_MODE_0 | SPI_MODE_CSHIGH)
00325 #elif SPI_MODE_AT45D1 == SPI_MODE_3
00326 #undef SPI_MODE_AT45D1
00327 #define SPI_MODE_AT45D1 (SPI_MODE_3 | SPI_MODE_CSHIGH)
00328 #endif
00329
00330 #endif
00331
00335 NUTSPINODE nodeAt45d1 = {
00336 NULL,
00337 NULL,
00338 SPI_RATE_AT45D1,
00339 SPI_MODE_AT45D1,
00340 8,
00341 0,
00342 &dcbAt45d1
00343 };
00344
00345 #ifndef SPI_RATE_AT45D2
00346 #define SPI_RATE_AT45D2 33000000
00347 #endif
00348
00349 #ifndef SPI_MODE_AT45D2
00350
00351 #ifdef SPI_CSHIGH_AT45D2
00352 #define SPI_MODE_AT45D2 (SPI_MODE_3 | SPI_MODE_CSHIGH)
00353 #else
00354 #define SPI_MODE_AT45D2 SPI_MODE_3
00355 #endif
00356
00357 #elif defined(SPI_CSHIGH_AT45D2)
00358
00359
00360 #if SPI_MODE_AT45D2 == SPI_MODE_0
00361 #undef SPI_MODE_AT45D2
00362 #define SPI_MODE_AT45D2 (SPI_MODE_0 | SPI_MODE_CSHIGH)
00363 #elif SPI_MODE_AT45D2 == SPI_MODE_3
00364 #undef SPI_MODE_AT45D2
00365 #define SPI_MODE_AT45D2 (SPI_MODE_3 | SPI_MODE_CSHIGH)
00366 #endif
00367
00368 #endif
00369
00373 NUTSPINODE nodeAt45d2 = {
00374 NULL,
00375 NULL,
00376 SPI_RATE_AT45D2,
00377 SPI_MODE_AT45D2,
00378 8,
00379 0,
00380 &dcbAt45d2
00381 };
00382
00383 #ifndef SPI_RATE_AT45D3
00384 #define SPI_RATE_AT45D3 33000000
00385 #endif
00386
00387 #ifndef SPI_MODE_AT45D3
00388
00389 #ifdef SPI_CSHIGH_AT45D3
00390 #define SPI_MODE_AT45D3 (SPI_MODE_3 | SPI_MODE_CSHIGH)
00391 #else
00392 #define SPI_MODE_AT45D3 SPI_MODE_3
00393 #endif
00394
00395 #elif defined(SPI_CSHIGH_AT45D3)
00396
00397
00398 #if SPI_MODE_AT45D3 == SPI_MODE_0
00399 #undef SPI_MODE_AT45D3
00400 #define SPI_MODE_AT45D3 (SPI_MODE_0 | SPI_MODE_CSHIGH)
00401 #elif SPI_MODE_AT45D3 == SPI_MODE_3
00402 #undef SPI_MODE_AT45D3
00403 #define SPI_MODE_AT45D3 (SPI_MODE_3 | SPI_MODE_CSHIGH)
00404 #endif
00405
00406 #endif
00407
00411 NUTSPINODE nodeAt45d3 = {
00412 NULL,
00413 NULL,
00414 SPI_RATE_AT45D3,
00415 SPI_MODE_AT45D3,
00416 8,
00417 0,
00418 &dcbAt45d3
00419 };
00420