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