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