4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
33 * \brief Function library for serial Flash memory.
35 * Module provide a kfile interface, that ensure an abstraction
36 * from comunication channel and give a standard interface.
37 * Typicaly this kind of memory use an SPI bus, but you should
38 * use another comunication channel you have defined.
41 * \author Daniele Basile <asterix@develer.com>
46 #include <cfg/macros.h>
47 #include <cfg/debug.h>
49 #include <drv/timer.h>
50 #include <drv/flash25.h>
53 #include <kern/proc.h>
57 * We use a spi bus, thus include hardware specific definition.
58 * If you use another channel you must redefine this macros.
62 #include <appconfig.h>
65 * Global definition of channel handler (usually SPI).
67 static KFile *channel;
70 * Wait until flash memory is ready.
72 static void flash25_waitReady(void)
80 kfile_putc(FLASH25_RDSR, channel);
81 stat = kfile_getc(channel);
85 if (!(stat & RDY_BIT))
95 * Send a single command to serial flash memory.
97 static void flash25_sendCmd(Flash25Opcode cmd)
101 kfile_putc(cmd, channel);
107 * flash25 init function.
108 * This function init a comunication channel and
109 * try to read manufacturer id of serial memory,
110 * then check if is equal to selected type.
112 static bool flash25_pin_init(void)
115 uint8_t manufacturer;
121 * Send read id productor opcode on
122 * comunication channel
123 * TODO:controllare se ha senso
125 kfile_putc(FLASH25_RDID, channel);
127 manufacturer = kfile_getc(channel);
128 device_id = kfile_getc(channel);
132 if((FLASH25_MANUFACTURER_ID == manufacturer) &&
133 (FLASH25_DEVICE_ID == device_id))
140 * Reopen a serial memory interface.
142 * For serial memory this function reinit only
143 * the size and seek_pos in kfile stucture.
144 * Return a kfile pointer, after assert check.
146 static KFile * flash25_reopen(struct KFile *fd)
148 KFILE_ASSERT_GENERIC(fd);
151 fd->size = FLASH25_MEM_SIZE;
153 kprintf("flash25 file opened\n");
158 * Close a serial memory interface.
160 * For serial memory this funtion do nothing,
161 * and return always 0.
163 static int flash25_close(UNUSED_ARG(struct KFile *,fd))
165 kprintf("flash25 file closed\n");
170 * Read \a _buf lenght \a size byte from serial flash memmory.
172 * For read in serial flash memory we
173 * enble cs pin and send one byte of read opcode,
174 * and then 3 byte of address of memory cell we
175 * want to read. After the last byte of address we
176 * can read data from so pin.
178 * \return the number of bytes read.
180 static size_t flash25_read(struct KFile *fd, void *buf, size_t size)
182 uint8_t *data = (uint8_t *)buf;
184 KFILE_ASSERT_GENERIC(fd);
186 ASSERT(fd->seek_pos + size <= fd->size);
187 size = MIN((uint32_t)size, fd->size - fd->seek_pos);
189 //kprintf("Reading at addr[%lu], size[%d]\n", fd->seek_pos, size);
192 kfile_putc(FLASH25_READ, channel);
196 * Address that we want to read.
198 kfile_putc((fd->seek_pos >> 16) & 0xFF, channel);
199 kfile_putc((fd->seek_pos >> 8) & 0xFF, channel);
200 kfile_putc(fd->seek_pos & 0xFF, channel);
202 kfile_read(channel, data, size);
206 fd->seek_pos += size;
212 * Write \a _buf in serial flash memory
214 * Before to write data into flash we must enable
215 * memory writing. To do this we send a WRE command opcode.
216 * After this command the flash is ready to be write, and so
217 * we send a PROGRAM opcode followed to 3 byte of
218 * address memory, at the end of last address byte
219 * we can send the data.
220 * When we finish to send all data, we disable cs
221 * and flash write received data bytes on its memory.
223 * \note: WARNING: you could write only on erased memory section!
224 * Each write time you could write max a memory page size,
225 * because if you write more than memory page size the
226 * address roll over to first byte of page.
228 * \return the number of bytes write.
230 static size_t flash25_write(struct KFile *fd, const void *_buf, size_t size)
232 flash25Offset_t offset;
233 flash25Size_t total_write = 0;
234 flash25Size_t wr_len;
235 const uint8_t *data = (const uint8_t *) _buf;
237 KFILE_ASSERT_GENERIC(fd);
238 ASSERT(fd->seek_pos + size <= fd->size);
240 size = MIN((flash25Size_t)size, fd->size - fd->seek_pos);
244 offset = fd->seek_pos % (flash25Size_t)FLASH25_PAGE_SIZE;
245 wr_len = MIN((flash25Size_t)size, FLASH25_PAGE_SIZE - (flash25Size_t)offset);
247 kprintf("[seek_pos-<%lu>, offset-<%d>]\n", fd->seek_pos, offset);
250 * We check serial flash memory state, and wait until ready-flag
257 * We could write only data not more long than one
260 * To write on serial flash memory we must first
261 * enable write with a WREN opcode command, before
262 * the PROGRAM opcode.
264 * \note: the same byte cannot be reprogrammed without
265 * erasing the whole sector first.
267 flash25_sendCmd(FLASH25_WREN);
270 kfile_putc(FLASH25_PROGRAM, channel);
273 * Address that we want to write.
275 kfile_putc((fd->seek_pos >> 16) & 0xFF, channel);
276 kfile_putc((fd->seek_pos >> 8) & 0xFF, channel);
277 kfile_putc(fd->seek_pos & 0xFF, channel);
279 kfile_write(channel, data, wr_len);
284 fd->seek_pos += wr_len;
286 total_write += wr_len;
289 kprintf("written %u bytes\n", total_write);
294 * Sector erase function.
296 * Erase a select \p sector of serial flash memory.
298 * \Note A sector size is FLASH25_SECTOR_SIZE.
299 * This operation could take a while.
301 void flash25_sectorErase(Flash25Sector sector)
305 * Erase a sector could take a while,
306 * for debug we measure that time
307 * see datasheet to compare this time.
309 DB(ticks_t start_time = timer_clock());
314 * To erase a sector of serial flash memory we must first
315 * enable write with a WREN opcode command, before
316 * the SECTOR_ERASE opcode. Sector is automatically
317 * determinate if any address within the sector
320 kfile_putc(FLASH25_WREN, channel);
321 kfile_putc(FLASH25_SECTORE_ERASE, channel);
324 * Address inside the sector that we want to
327 kfile_putc(sector, channel);
332 * We check serial flash memory state, and wait until ready-flag
337 DB(kprintf("Erased sector [%d] in %d ms\n", sector, ticks_to_ms(timer_clock() - start_time)));
342 * Chip erase function.
344 * Erase all sector of serial flash memory.
346 * \Note This operation could take a while.
348 void flash25_chipErase(void)
351 * Erase all chip could take a while,
352 * for debug we measure that time
353 * see datasheet to compare this time.
355 DB(ticks_t start_time = timer_clock());
358 * To erase serial flash memory we must first
359 * enable write with a WREN opcode command, before
360 * the CHIP_ERASE opcode.
362 flash25_sendCmd(FLASH25_WREN);
363 flash25_sendCmd(FLASH25_CHIP_ERASE);
366 * We check serial flash memory state, and wait until ready-flag
371 DB(kprintf("Erased all memory in %d ms\n", ticks_to_ms(timer_clock() - start_time)));
376 * Init data flash memory interface.
378 void flash25_init(struct KFile *fd, struct KFile *_channel)
380 //Set kfile struct type as a generic kfile structure.
381 DB(fd->_type = KFT_GENERIC);
383 // Set up data flash programming functions.
384 fd->reopen = flash25_reopen;
385 fd->close = flash25_close;
386 fd->read = flash25_read;
387 fd->write = flash25_write;
388 fd->seek = kfile_genericSeek;
391 * Init a local channel structure and flash kfile interface.
397 * Init data flash memory and micro pin.
399 if (!flash25_pin_init())
406 * Test function for flash25.
408 * \note: This implentation use a SPI channel.
410 bool flash25_test(KFile *channel)
413 uint8_t test_buf[256];
416 * Init a spi kfile interface and
419 flash25_init(&fd, channel);
421 kprintf("Init serial flash\n");
425 flash25_sectorErase(FLASH25_SECT1);
426 flash25_sectorErase(FLASH25_SECT2);
427 flash25_sectorErase(FLASH25_SECT3);
428 flash25_sectorErase(FLASH25_SECT4);
431 * Launche a kfile test interface.
433 kprintf("Kfile test start..\n");
434 if (!kfile_test(&fd, test_buf, NULL, sizeof(test_buf)))
439 #endif /* CONFIG_TEST */