flash25.c

Go to the documentation of this file.
00001 
00043 /*
00044  * We use a spi bus, thus include hardware specific definition.
00045  * If you use another channel you must redefine this macros.
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> /* cpu_relax() */
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      * Send read id productor opcode on
00112      * comunication channel
00113      * TODO:controllare se ha senso
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     //kprintf("Reading at addr[%lu], size[%d]\n", fd->seek_pos, size);
00180     CS_ENABLE();
00181 
00182     kfile_putc(FLASH25_READ, fd->channel);
00183 
00184 
00185     /*
00186      * Address that we want to read.
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          * We check serial flash memory state, and wait until ready-flag
00242          * is high.
00243          */
00244         flash25_waitReady(fd);
00245 
00246         /*
00247          * Start write cycle.
00248          * We could write only data not more long than one
00249          * page size.
00250          *
00251          * To write on serial flash memory we must first
00252          * enable write with a WREN opcode command, before
00253          * the PROGRAM opcode.
00254          *
00255          * \note: the same byte cannot be reprogrammed without
00256          * erasing the whole sector first.
00257          */
00258         flash25_sendCmd(fd, FLASH25_WREN);
00259 
00260         CS_ENABLE();
00261         kfile_putc(FLASH25_PROGRAM, fd->channel);
00262 
00263         /*
00264          * Address that we want to write.
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      * Erase a sector could take a while,
00297      * for debug we measure that time
00298      * see datasheet to compare this time.
00299      */
00300     DB(ticks_t start_time = timer_clock());
00301 
00302     CS_ENABLE();
00303 
00304     /*
00305      * To erase a sector of serial flash memory we must first
00306      * enable write with a WREN opcode command, before
00307      * the SECTOR_ERASE opcode. Sector is automatically
00308      * determinate if any address within the sector
00309      * is selected.
00310      */
00311     kfile_putc(FLASH25_WREN, fd->channel);
00312     kfile_putc(FLASH25_SECTORE_ERASE,fd-> channel);
00313 
00314     /*
00315      * Address inside the sector that we want to
00316      * erase.
00317      */
00318     kfile_putc(sector, fd->channel);
00319 
00320     CS_DISABLE();
00321 
00322     /*
00323      * We check serial flash memory state, and wait until ready-flag
00324      * is hight.
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      * Erase all chip could take a while,
00342      * for debug we measure that time
00343      * see datasheet to compare this time.
00344      */
00345     DB(ticks_t start_time = timer_clock());
00346 
00347     /*
00348      * To erase serial flash memory we must first
00349      * enable write with a WREN opcode command, before
00350      * the CHIP_ERASE opcode.
00351      */
00352     flash25_sendCmd(fd, FLASH25_WREN);
00353     flash25_sendCmd(fd, FLASH25_CHIP_ERASE);
00354 
00355     /*
00356      * We check serial flash memory state, and wait until ready-flag
00357      * is high.
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      //Set kfile struct type as a generic kfile structure.
00375     DB(fd->fd._type = KFT_FLASH25);
00376 
00377     // Set up data flash programming functions.
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      * Init a local channel structure and flash kfile interface.
00386      */
00387     fd->channel = ch;
00388     flash25_reopen(&fd->fd);
00389 
00390     /*
00391      * Init data flash memory and micro pin.
00392      */
00393     if (!flash25_pin_init(fd))
00394         ASSERT(0);
00395 }
00396 
00397