flash25.c
Go to the documentation of this file.00001
00044 #include <avr/io.h>
00045
00046 #include <cfg/macros.h>
00047 #include <cfg/debug.h>
00048
00049 #include <drv/timer.h>
00050 #include <drv/flash25.h>
00051
00052 #if CONFIG_KERNEL
00053 #include <kern/proc.h>
00054 #endif
00055
00056
00057
00058
00059
00060 #include "hw_spi.h"
00061
00062 #include <appconfig.h>
00063
00067 static KFile *channel;
00068
00072 static void flash25_waitReady(void)
00073 {
00074 uint8_t stat;
00075
00076 while (1)
00077 {
00078 CS_ENABLE();
00079
00080 kfile_putc(FLASH25_RDSR, channel);
00081 stat = kfile_getc(channel);
00082
00083 CS_DISABLE();
00084
00085 if (!(stat & RDY_BIT))
00086 break;
00087 #if CONFIG_KERNEL
00088 else
00089 proc_switch();
00090 #endif
00091 }
00092 }
00093
00097 static void flash25_sendCmd(Flash25Opcode cmd)
00098 {
00099 CS_ENABLE();
00100
00101 kfile_putc(cmd, channel);
00102
00103 CS_DISABLE();
00104 }
00105
00112 static bool flash25_pin_init(void)
00113 {
00114 uint8_t device_id;
00115 uint8_t manufacturer;
00116
00117 SPI_HW_INIT();
00118
00119 CS_ENABLE();
00120
00121
00122
00123
00124
00125 kfile_putc(FLASH25_RDID, channel);
00126
00127 manufacturer = kfile_getc(channel);
00128 device_id = kfile_getc(channel);
00129
00130 CS_DISABLE();
00131
00132 if((FLASH25_MANUFACTURER_ID == manufacturer) &&
00133 (FLASH25_DEVICE_ID == device_id))
00134 return true;
00135 else
00136 return false;
00137 }
00138
00146 static KFile * flash25_reopen(struct KFile *fd)
00147 {
00148 KFILE_ASSERT_GENERIC(fd);
00149
00150 fd->seek_pos = 0;
00151 fd->size = FLASH25_MEM_SIZE;
00152
00153 kprintf("flash25 file opened\n");
00154 return fd;
00155 }
00156
00163 static int flash25_close(UNUSED_ARG(struct KFile *,fd))
00164 {
00165 kprintf("flash25 file closed\n");
00166 return 0;
00167 }
00168
00180 static size_t flash25_read(struct KFile *fd, void *buf, size_t size)
00181 {
00182 uint8_t *data = (uint8_t *)buf;
00183
00184 KFILE_ASSERT_GENERIC(fd);
00185
00186 ASSERT(fd->seek_pos + size <= fd->size);
00187 size = MIN((uint32_t)size, fd->size - fd->seek_pos);
00188
00189
00190 CS_ENABLE();
00191
00192 kfile_putc(FLASH25_READ, channel);
00193
00194
00195
00196
00197
00198 kfile_putc((fd->seek_pos >> 16) & 0xFF, channel);
00199 kfile_putc((fd->seek_pos >> 8) & 0xFF, channel);
00200 kfile_putc(fd->seek_pos & 0xFF, channel);
00201
00202 kfile_read(channel, data, size);
00203
00204 CS_DISABLE();
00205
00206 fd->seek_pos += size;
00207
00208 return size;
00209 }
00210
00230 static size_t flash25_write(struct KFile *fd, const void *_buf, size_t size)
00231 {
00232 flash25Offset_t offset;
00233 flash25Size_t total_write = 0;
00234 flash25Size_t wr_len;
00235 const uint8_t *data = (const uint8_t *) _buf;
00236
00237 KFILE_ASSERT_GENERIC(fd);
00238 ASSERT(fd->seek_pos + size <= fd->size);
00239
00240 size = MIN((flash25Size_t)size, fd->size - fd->seek_pos);
00241
00242 while (size)
00243 {
00244 offset = fd->seek_pos % (flash25Size_t)FLASH25_PAGE_SIZE;
00245 wr_len = MIN((flash25Size_t)size, FLASH25_PAGE_SIZE - (flash25Size_t)offset);
00246
00247 kprintf("[seek_pos-<%lu>, offset-<%d>]\n", fd->seek_pos, offset);
00248
00249
00250
00251
00252
00253 flash25_waitReady();
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 flash25_sendCmd(FLASH25_WREN);
00268
00269 CS_ENABLE();
00270 kfile_putc(FLASH25_PROGRAM, channel);
00271
00272
00273
00274
00275 kfile_putc((fd->seek_pos >> 16) & 0xFF, channel);
00276 kfile_putc((fd->seek_pos >> 8) & 0xFF, channel);
00277 kfile_putc(fd->seek_pos & 0xFF, channel);
00278
00279 kfile_write(channel, data, wr_len);
00280
00281 CS_DISABLE();
00282
00283 data += wr_len;
00284 fd->seek_pos += wr_len;
00285 size -= wr_len;
00286 total_write += wr_len;
00287 }
00288
00289 kprintf("written %u bytes\n", total_write);
00290 return total_write;
00291 }
00292
00301 void flash25_sectorErase(Flash25Sector sector)
00302 {
00303
00304
00305
00306
00307
00308
00309 DB(ticks_t start_time = timer_clock());
00310
00311 CS_ENABLE();
00312
00313
00314
00315
00316
00317
00318
00319
00320 kfile_putc(FLASH25_WREN, channel);
00321 kfile_putc(FLASH25_SECTORE_ERASE, channel);
00322
00323
00324
00325
00326
00327 kfile_putc(sector, channel);
00328
00329 CS_DISABLE();
00330
00331
00332
00333
00334
00335 flash25_waitReady();
00336
00337 DB(kprintf("Erased sector [%d] in %d ms\n", sector, ticks_to_ms(timer_clock() - start_time)));
00338
00339 }
00340
00348 void flash25_chipErase(void)
00349 {
00350
00351
00352
00353
00354
00355 DB(ticks_t start_time = timer_clock());
00356
00357
00358
00359
00360
00361
00362 flash25_sendCmd(FLASH25_WREN);
00363 flash25_sendCmd(FLASH25_CHIP_ERASE);
00364
00365
00366
00367
00368
00369 flash25_waitReady();
00370
00371 DB(kprintf("Erased all memory in %d ms\n", ticks_to_ms(timer_clock() - start_time)));
00372
00373 }
00374
00378 void flash25_init(struct KFile *fd, struct KFile *_channel)
00379 {
00380
00381 DB(fd->_type = KFT_GENERIC);
00382
00383
00384 fd->reopen = flash25_reopen;
00385 fd->close = flash25_close;
00386 fd->read = flash25_read;
00387 fd->write = flash25_write;
00388 fd->seek = kfile_genericSeek;
00389
00390
00391
00392
00393 channel = _channel;
00394 flash25_reopen(fd);
00395
00396
00397
00398
00399 if (!flash25_pin_init())
00400 ASSERT(0);
00401 }
00402
00403 #if CONFIG_TEST
00404
00410 bool flash25_test(KFile *channel)
00411 {
00412 KFile fd;
00413 uint8_t test_buf[256];
00414
00415
00416
00417
00418
00419 flash25_init(&fd, channel);
00420
00421 kprintf("Init serial flash\n");
00422
00423 flash25_chipErase();
00424
00425 flash25_sectorErase(FLASH25_SECT1);
00426 flash25_sectorErase(FLASH25_SECT2);
00427 flash25_sectorErase(FLASH25_SECT3);
00428 flash25_sectorErase(FLASH25_SECT4);
00429
00430
00431
00432
00433 kprintf("Kfile test start..\n");
00434 if (!kfile_test(&fd, test_buf, NULL, sizeof(test_buf)))
00435 return false;
00436
00437 return true;
00438 }
00439 #endif