flash25.c
Go to the documentation of this file.00001
00043
00044
00045
00046
00047 #include "hw/hw_spi.h"
00048
00049 #include <cfg/macros.h>
00050 #include <cfg/debug.h>
00051
00052 #include <drv/timer.h>
00053 #include <drv/flash25.h>
00054
00055 #include <kern/kfile.h>
00056
00057 #include <cpu/power.h>
00058
00059 #warning FIXME:This file was changed, but is untested!
00060
00064 static void flash25_waitReady(Flash25 *fd)
00065 {
00066 uint8_t stat;
00067
00068 while (1)
00069 {
00070 CS_ENABLE();
00071
00072 kfile_putc(FLASH25_RDSR, fd->channel);
00073 stat = kfile_getc(fd->channel);
00074
00075 CS_DISABLE();
00076
00077 if (!(stat & RDY_BIT))
00078 break;
00079
00080 cpu_relax();
00081 }
00082 }
00083
00087 static void flash25_sendCmd(Flash25 *fd, Flash25Opcode cmd)
00088 {
00089 CS_ENABLE();
00090
00091 kfile_putc(cmd, fd->channel);
00092
00093 CS_DISABLE();
00094 }
00095
00102 static bool flash25_pin_init(Flash25 *fd)
00103 {
00104 uint8_t device_id;
00105 uint8_t manufacturer;
00106
00107 SPI_HW_INIT();
00108
00109 CS_ENABLE();
00110
00111
00112
00113
00114
00115 kfile_putc(FLASH25_RDID, fd->channel);
00116
00117 manufacturer = kfile_getc(fd->channel);
00118 device_id = kfile_getc(fd->channel);
00119
00120 CS_DISABLE();
00121
00122 if((FLASH25_MANUFACTURER_ID == manufacturer) &&
00123 (FLASH25_DEVICE_ID == device_id))
00124 return true;
00125 else
00126 return false;
00127 }
00128
00136 static KFile * flash25_reopen(struct KFile *_fd)
00137 {
00138 Flash25 *fd = FLASH25_CAST(_fd);
00139
00140 fd->fd.seek_pos = 0;
00141 fd->fd.size = FLASH25_MEM_SIZE;
00142
00143 kprintf("flash25 file opened\n");
00144 return &fd->fd;
00145 }
00146
00153 static int flash25_close(UNUSED_ARG(struct KFile *,fd))
00154 {
00155 kprintf("flash25 file closed\n");
00156 return 0;
00157 }
00158
00170 static size_t flash25_read(struct KFile *_fd, void *buf, size_t size)
00171 {
00172 uint8_t *data = (uint8_t *)buf;
00173
00174 Flash25 *fd = FLASH25_CAST(_fd);
00175
00176 ASSERT(fd->fd.seek_pos + (kfile_off_t)size <= fd->fd.size);
00177 size = MIN((kfile_off_t)size, fd->fd.size - fd->fd.seek_pos);
00178
00179
00180 CS_ENABLE();
00181
00182 kfile_putc(FLASH25_READ, fd->channel);
00183
00184
00185
00186
00187
00188 kfile_putc((fd->fd.seek_pos >> 16) & 0xFF, fd->channel);
00189 kfile_putc((fd->fd.seek_pos >> 8) & 0xFF, fd->channel);
00190 kfile_putc(fd->fd.seek_pos & 0xFF, fd->channel);
00191
00192 kfile_read(fd->channel, data, size);
00193
00194 CS_DISABLE();
00195
00196 fd->fd.seek_pos += size;
00197
00198 return size;
00199 }
00200
00220 static size_t flash25_write(struct KFile *_fd, const void *_buf, size_t size)
00221 {
00222 flash25Offset_t offset;
00223 flash25Size_t total_write = 0;
00224 flash25Size_t wr_len;
00225 const uint8_t *data = (const uint8_t *) _buf;
00226
00227 Flash25 *fd = FLASH25_CAST(_fd);
00228
00229 ASSERT(fd->fd.seek_pos + (kfile_off_t)size <= fd->fd.size);
00230
00231 size = MIN((kfile_off_t)size, fd->fd.size - fd->fd.seek_pos);
00232
00233 while (size)
00234 {
00235 offset = fd->fd.seek_pos % (flash25Size_t)FLASH25_PAGE_SIZE;
00236 wr_len = MIN((flash25Size_t)size, FLASH25_PAGE_SIZE - (flash25Size_t)offset);
00237
00238 kprintf("[seek_pos-<%lu>, offset-<%d>]\n", fd->fd.seek_pos, offset);
00239
00240
00241
00242
00243
00244 flash25_waitReady(fd);
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 flash25_sendCmd(fd, FLASH25_WREN);
00259
00260 CS_ENABLE();
00261 kfile_putc(FLASH25_PROGRAM, fd->channel);
00262
00263
00264
00265
00266 kfile_putc((fd->fd.seek_pos >> 16) & 0xFF, fd->channel);
00267 kfile_putc((fd->fd.seek_pos >> 8) & 0xFF, fd->channel);
00268 kfile_putc(fd->fd.seek_pos & 0xFF, fd->channel);
00269
00270 kfile_write(fd->channel, data, wr_len);
00271
00272 CS_DISABLE();
00273
00274 data += wr_len;
00275 fd->fd.seek_pos += wr_len;
00276 size -= wr_len;
00277 total_write += wr_len;
00278 }
00279
00280 kprintf("written %lu bytes\n", total_write);
00281 return total_write;
00282 }
00283
00292 void flash25_sectorErase(Flash25 *fd, Flash25Sector sector)
00293 {
00294
00295
00296
00297
00298
00299
00300 DB(ticks_t start_time = timer_clock());
00301
00302 CS_ENABLE();
00303
00304
00305
00306
00307
00308
00309
00310
00311 kfile_putc(FLASH25_WREN, fd->channel);
00312 kfile_putc(FLASH25_SECTORE_ERASE,fd-> channel);
00313
00314
00315
00316
00317
00318 kfile_putc(sector, fd->channel);
00319
00320 CS_DISABLE();
00321
00322
00323
00324
00325
00326 flash25_waitReady(fd);
00327
00328 DB(kprintf("Erased sector [%ld] in %ld ms\n", (unsigned long)sector, (unsigned long)ticks_to_ms(timer_clock() - start_time)));
00329 }
00330
00338 void flash25_chipErase(Flash25 *fd)
00339 {
00340
00341
00342
00343
00344
00345 DB(ticks_t start_time = timer_clock());
00346
00347
00348
00349
00350
00351
00352 flash25_sendCmd(fd, FLASH25_WREN);
00353 flash25_sendCmd(fd, FLASH25_CHIP_ERASE);
00354
00355
00356
00357
00358
00359 flash25_waitReady(fd);
00360
00361 DB(kprintf("Erased all memory in %ld ms\n", ticks_to_ms(timer_clock() - start_time)));
00362
00363 }
00364
00368 void flash25_init(Flash25 *fd, KFile *ch)
00369 {
00370
00371 ASSERT(fd);
00372 ASSERT(ch);
00373
00374
00375 DB(fd->fd._type = KFT_FLASH25);
00376
00377
00378 fd->fd.reopen = flash25_reopen;
00379 fd->fd.close = flash25_close;
00380 fd->fd.read = flash25_read;
00381 fd->fd.write = flash25_write;
00382 fd->fd.seek = kfile_genericSeek;
00383
00384
00385
00386
00387 fd->channel = ch;
00388 flash25_reopen(&fd->fd);
00389
00390
00391
00392
00393 if (!flash25_pin_init(fd))
00394 ASSERT(0);
00395 }
00396
00397