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 AT45DBXX Data Flash memory.
36 * \version $Id: dataflash.c 15379 2007-03-28 15:46:09Z asterix $
37 * \author Daniele Basile <asterix@develer.com>
41 #include <appconfig.h>
44 #include <cfg/macros.h>
45 #include <cfg/debug.h>
46 #include <cfg/module.h>
47 #include <drv/timer.h>
49 #include <drv/dataflash.h>
53 #warning This driver must be test before use!
55 * Global variable for store current and previous data
56 * flash memory page address during operation of writing.
58 static dataflash_t previous_page = 0;
59 static bool page_modified = false;
63 * Send a generic command to data flash memory.
64 * This function send only 4 byte, for opcode, page address and
67 static void send_cmd(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode)
71 * Make sure to toggle CS signal in order,
72 * and reset dataflash command decoder.
74 * \note This is equivalent to CS_DISABLE() immediately followed by CS_ENABLE()
80 * To send one command to data flash memory, we send 4 byte.
81 * First byte is opcode command, second and third byte are
82 * page address, in last byte we write a byte page address.
83 * (see datasheet for more detail).
85 * \note Generaly a defaul memory page size is more than 256 byte.
86 * In this case we need for addressing a byte in one page more than
87 * 8 bit, so we put in fourth byte low part of address byte, and
88 * hight part of address byte in third byte togheter low par of page
101 spi_sendRecv((uint8_t)(page_addr >> (16 - DATAFLASH_PAGE_ADDRESS_BIT)));
102 spi_sendRecv((uint8_t)((page_addr << (DATAFLASH_PAGE_ADDRESS_BIT - 8)) + (byte_addr >> 8)));
105 * Send byte page address.
107 spi_sendRecv((uint8_t)byte_addr);
113 * Reset dataflash memory function.
115 * This function reset data flash memory
116 * with one pulse reset long about 10usec.
119 static void dataflash_reset(void)
123 timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH));
126 timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH));
130 * dataflash init function.
131 * This function initialize a micro pin and
132 * SPI driver, and test if data flash memory
133 * density is the same wich define in dataflash.h.
135 MOD_DEFINE(dataflash);
136 static bool dataflash_pin_init(void)
143 WRITE_ENABLE(); //pilot wp pin.
150 stat = dataflash_stat();
155 * 2,3,4,5 bits of 1 byte status register
156 * indicate a device density of dataflash memory
157 * (see datasheet for more detail.)
159 GET_ID_DESITY_DEVICE(stat);
161 if(stat == DATAFLASH_ID_DEVICE_DENSITY)
170 * Read status register of dataflah memory.
173 static uint8_t dataflash_stat(void)
178 * Make sure to toggle CS signal in order,
179 * and reset dataflash command decoder.
183 stat = spi_sendRecv(DFO_READ_STATUS);
184 stat = spi_sendRecv(0x00);
187 * Note: this function could be call one more time
188 * to check register status (es. check if memory has been
189 * teminate one operation), and so we don't disable CS to
190 * allow fast reading of register status.
197 * Send one command to data flash memory, and
198 * return status register value.
201 static uint8_t dataflash_cmd(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode)
206 send_cmd(page_addr, byte_addr, opcode);
211 * We chech data flash memory state, and wait until busy-flag
214 while(!(dataflash_stat() & BUSY_BIT));
216 stat = dataflash_stat();
219 * Data flash has completed a bus cycle, so disable CS.
228 * Read one byte from main data flash memory or buffer data
231 static uint8_t dataflash_read_byte(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode)
235 send_cmd(page_addr, byte_addr, opcode);
237 #if CONFIG_DATA_FLASH == DATAFLASH_AT45DB041B
238 if(opcode == DFO_READ_FLASH_MEM_BYTE)
241 * Send 24 don't care bit.
250 spi_sendRecv(0x00); //Send 8 don't care bit.
251 data = spi_sendRecv(0x00); //Read byte.
259 * Read \a len bytes from main data flash memory or buffer data
260 * flash memory, and put it in \a *block.
262 static void dataflash_read_block(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode, uint8_t *block, dataflashSize_t len)
265 send_cmd(page_addr, byte_addr, opcode);
267 if(opcode == DFO_READ_FLASH_MEM_BYTE)
270 * Send 24 don't care bit.
278 spi_sendRecv(0x00); //Send 8 don't care bit.
279 spi_read(block, len); //Read len bytes ad put in block buffer.
288 * Write \a len bytes in buffer buffer data flash memory.
290 * \note Isn't possible to write bytes directly in main memory data
291 * flash. To perform write in main memory you must before write in buffer
292 * data flash memory, an then send command to write page in main memory.
294 static void dataflash_write_block(dataflashOffset_t byte_addr, DataFlashOpcode opcode, uint8_t *block, dataflashSize_t len)
297 send_cmd(0x00, byte_addr, opcode);
299 spi_write(block, len); //Write len bytes.
307 * Load selct page from dataflash memory to buffer.
309 static void dataflash_loadPage(dataflash_t page_addr)
311 dataflash_cmd(page_addr, 0x00, DFO_MOV_MEM_TO_BUFF1);
315 * Flush select page (stored in buffer) in data flash main memory page.
317 void dataflash_flush(void)
321 dataflash_cmd(previous_page, 0x00, DFO_WRITE_BUFF1_TO_MEM_E);
323 page_modified = false;
325 kprintf("\n::=> Flush page:... <%ld>\n", previous_page);
329 /* Kfile interface section */
332 * Open data flash file \a fd
333 * \a name and \a mode are unused, cause flash memory is
334 * threated like one file.
336 static bool dataflash_open(struct _KFile *fd, UNUSED_ARG(const char *, name), UNUSED_ARG(int, mode))
338 MOD_CHECK(dataflash);
342 fd->size = (dataflashAddr_t)DATAFLASH_PAGE_SIZE * (dataflashAddr_t)DATAFLASH_NUM_PAGE;
344 /* Load select page memory from data flash memory*/
345 dataflash_loadPage(previous_page);
347 kprintf("dataflash file opened\n");
354 static bool dataflash_close(UNUSED_ARG(struct _KFile *,fd))
357 kprintf("dataflash file closed\n");
362 * Move \a fd file seek position of \a offset bytes
363 * from current position.
365 static int32_t dataflash_seek(struct _KFile *fd, kfile_off_t offset, KSeekMode whence)
376 seek_pos = fd->size - 1;
379 seek_pos = fd->seek_pos;
389 if (seek_pos + offset > fd->size)
395 fd->seek_pos = seek_pos + offset;
396 kprintf("Flash seek to [%u]\n", fd->seek_pos);
402 * Read \a _buf lenght \a size byte from data flash memmory.
404 * \note For read in data flash memory, we
405 * check flag page_modified, if is true (that mean
406 * we had been written a byte in buffer memory) we
407 * flush current page in data flash main memory, and
408 * then read byte from memory, else we read byte
409 * directly from data flash main memory.
411 * \return the number of bytes read.
413 static size_t dataflash_read(struct _KFile *fd, void *buf, size_t size)
415 dataflashOffset_t byte_addr;
416 dataflashAddr_t page_addr;
417 uin8_t *data = (uint8_t *)buf;
420 ASSERT(fd->seek_pos + size <= fd->size);
421 size = MIN((uint32_t)size, fd->size - fd->seek_pos);
423 kprintf("Reading at pos[%u]\n", fd->seek_pos);
426 * We select page and offest from absolute address.
428 page_addr = fd->seek_pos / (dataflashAddr_t)DATAFLASH_PAGE_SIZE;
429 byte_addr = fd->seek_pos % (dataflashOffset_t)DATAFLASH_PAGE_SIZE;
432 kprintf(" [page-<%ld>, byte-<%ld>]", page_addr, byte_addr);
435 * Flush current page in main memory if
436 * we had been written a byte in memory
441 * Read byte in main page data flash memory.
443 dataflash_read_block(page_addr, byte_addr, DFO_READ_FLASH_MEM_BYTE, data, size);
445 fd->seek_pos += size;
446 kprintf(" ::=> Read data: %02x\n",data);
452 * Write \a _buf in data flash memory
454 * \note For write \a _buf in data flash memory, we must
455 * before write in buffer data flash memory, and at end of write,
456 * we put page in data flash main memory. If we write in two
457 * different page, we put in main memory current page and reload
458 * page witch we want write.
460 * \return the number of bytes write.
462 static size_t dataflash_write(struct _KFile *fd, const void *_buf, size_t size)
465 dataflashOffset_t byte_addr;
466 dataflashAddr_t current_page;
468 uint8_t *data = (uint8_t *) _buf;
470 ASSERT(fd->seek_pos + size <= fd->size);
471 size = MIN((uint32_t)size, fd->size - fd->seek_pos);
473 kprintf("Writing at pos[%u]\n", fd->seek_pos);
478 * We select page and offest from absolute address.
480 current_page = fd->seek_pos / (dataflashAddr_t)DATAFLASH_PAGE_SIZE;
481 byte_addr = fd->seek_pos % (dataflashOffset_t)DATAFLASH_PAGE_SIZE;
484 size_t wr_len = MIN(size, DATAFLASH_PAGE_SIZE - byte_addr);
486 kprintf(" [page-<%ld>, byte-<%ld>]",current_page, byte_addr);
488 if (current_page != previous_page)
490 /* Flush current page in main memory*/
492 /* Load select page memory from data flash memory*/
493 dataflash_loadPage(current_page);
495 previous_page = current_page;
496 kprintf(" >> Load page: <%ld> ",current_page);
499 * Write byte in current page, and set true
500 * page_modified flag.
502 dataflash_write_byte(byte_addr, DFO_WRITE_BUFF1, data);
503 page_modified = true;
507 fd->seek_pos += wr_len;
509 total_write += wr_len;
512 kprintf("written %u bytes\n", total_write);
517 * Init data flash memory interface.
519 void dataflash_init(struct _KFile *fd)
521 // Set up data flash programming functions.
522 fd->open = dataflash_open;
523 fd->close = dataflash_close;
524 fd->read = dataflash_read;
525 fd->write = dataflash_write;
526 fd->seek = dataflash_seek;
528 // Init data flash memory and micro pin.
529 ASSERT(dataflash_pin_init());
533 * Test function for dataflash.
535 * This function test check low level driver for
536 * AT45xx (see dataflash.h for more info) data flash memory.
537 * We write a string in memory in some page ad read it.
539 void dataflash_test(void)
545 uint8_t test_buf[] = "0123456789 Develer s.r.l.";
546 uint8_t cmp_buf[sizeof(test_buf)];
548 int tb_len = sizeof(test_buf);
551 kprintf("\n======= Data Flash test function =========================================\n");
552 kprintf("\nThe string test is: %s\n\n", test_buf);
554 fd.open(&fd, NULL, 0);
559 if (!fd.seek(&fd, 0, KSM_SEEK_SET))
560 goto dataflash_test_end;
562 // Test flash write to address 0 (page 0)
563 tmp_len = fd.write(&fd, test_buf, tb_len);
564 if (tb_len != tmp_len)
566 kprintf("Test 1: Wrong numer write bytes! expecteded [%d], write [%d]\n", tb_len, tmp_len);
567 goto dataflash_test_end;
571 if (fd.seek(&fd, 0, KSM_SEEK_SET) != 0)
572 goto dataflash_test_end;
575 // Test flash read to address 0 (page 0)
576 tmp_len = fd.read(&fd, cmp_buf, tb_len);
577 if (tb_len != tmp_len)
579 kprintf("Test 1: Wrong numer read bytes! expecteded [%d], read [%d]\n", tb_len, tmp_len);
580 goto dataflash_test_end;
583 // Compare if they are equal
584 if ((memcmp(cmp_buf,test_buf, tb_len) == 0))
586 kprintf("Test 1: Readed test buf don't much!\n");
587 goto dataflash_test_end;
592 // Go to middle address memory.
593 if (!fd.seek(&fd, (((dataflashAddr_t)DFLASH_PAGE_SIZE * (dataflashAddr_t)DFLASH_NUM_PAGE) / 2), SEEK_CUR))
594 goto dataflash_test_end;
597 // Test flash write at the middle of memory
598 tmp_len = fd.write(&fd, test_buf, tb_len);
599 if (tb_len != tmp_len)
601 kprintf("Test 2: Wrong numer write bytes! expecteded [%d], write [%d]\n", tb_len, tmp_len);
602 goto dataflash_test_end;
605 // Go to middle address memory.
606 if (!fd.seek(&fd, (((dataflashAddr_t)DFLASH_PAGE_SIZE * (dataflashAddr_t)DFLASH_NUM_PAGE) / 2), SEEK_CUR))
607 goto dataflash_test_end;
610 // Test flash read at the middle of memory
611 tmp_len = fd.read(&fd, cmp_buf, tb_len);
612 if (tb_len != tmp_len)
614 kprintf("Test 2: Wrong numer read bytes! expecteded [%d], read [%d]\n", tb_len, tmp_len);
615 goto dataflash_test_end;
618 // Compare if they are equal
619 if ((memcmp(cmp_buf,test_buf, tb_len) == 0))
621 kprintf("Test 2: Readed test buf don't much!\n");
622 goto dataflash_test_end;
626 // Go to end of data flash.
627 if(!fd.seek(&fd, ((dataflashAddr_t)DFLASH_PAGE_SIZE * (dataflashAddr_t)DFLASH_NUM_PAGE) - len_tb, SEEK_END))
628 goto dataflash_test_end;
631 // Test flash write at the end of memory
632 tmp_len = fd.write(&fd, test_buf, tb_len);
633 if (tb_len != tmp_len)
635 kprintf("Test 3: Wrong numer write bytes! expecteded [%d], write [%d]\n", tb_len, tmp_len);
636 goto dataflash_test_end;
639 // Go to end of data flash.
640 if(!fd.seek(&fd, ((dataflashAddr_t)DFLASH_PAGE_SIZE * (dataflashAddr_t)DFLASH_NUM_PAGE) - len_tb, SEEK_END))
641 goto dataflash_test_end;
644 // Test flash read at the end of memory
645 tmp_len = fd.read(&fd, cmp_buf, tb_len);
646 if (tb_len != tmp_len)
648 kprintf("Test 3: Wrong numer read bytes! expecteded [%d], read [%d]\n", tb_len, tmp_len);
649 goto dataflash_test_end;
652 // Compare if they are equal
653 if ((memcmp(cmp_buf,test_buf, tb_len) == 0))
655 kprintf("Test 3: Readed test buf don't much!\n");
656 goto dataflash_test_end;
661 kprintf("\n====== Test end ===========================================================\n");