* \brief Function library for AT45DBXX Data Flash memory.
*
*
- * \version $Id: dataflash.c 15379 2007-03-28 15:46:09Z asterix $
+ * \version $Id: dataflash.c 20677 2008-02-19 14:29:52Z batt $
* \author Daniele Basile <asterix@develer.com>
+ * \author Francesco Sacchi <batt@develer.com>
*/
-
+#include "dataflash.h"
#include <appconfig.h>
-#include <avr/io.h>
#include <cfg/macros.h>
#include <cfg/debug.h>
#include <cfg/module.h>
#include <drv/timer.h>
-#include <drv/spi.h>
-#include <drv/dataflash.h>
+#include <kern/kfile.h>
-#include "hw_spi.h"
+#if CONFIG_KERNEL
+#include <kern/proc.h>
+#endif
+#include <string.h>
/**
- * Global variable for store current and previous data
- * flash memory page address during operation of writing.
+ * Array used to describe dataflash memory devices currently supported.
*/
-static dataflash_t previous_page = 0;
-static bool page_modified = false;
+static const DataflashInfo mem_info[] =
+{
+ {
+ /* AT45DB041B */
+ .density_id = 0x07,
+ .page_size = 264,
+ .page_bits = 9,
+ .page_cnt = 2048,
+ .read_cmd = DFO_READ_FLASH_MEM_BYTE_B,
+ },
+ {
+ /* AT45DB081D */
+ .density_id = 0x09,
+ .page_size = 264,
+ .page_bits = 9,
+ .page_cnt = 4096,
+ .read_cmd = DFO_READ_FLASH_MEM_BYTE_D,
+ },
+ {
+ /* AT45DB161D */
+ .density_id = 0x0B,
+ .page_size = 528,
+ .page_bits = 10,
+ .page_cnt = 4096,
+ .read_cmd = DFO_READ_FLASH_MEM_BYTE_D,
+ },
+ /* Add other memories here */
+};
+
+STATIC_ASSERT(countof(mem_info) == DFT_CNT);
+/**
+ * Macro that toggle CS of dataflash.
+ * \note This is equivalent to fd->setCS(false) immediately followed by fd->setCS(true).
+ */
+INLINE void CS_TOGGLE(KFileDataflash *fd)
+{
+ fd->setCS(false);
+ fd->setCS(true);
+}
/**
- * Send a generic command to data flash memory.
- * This function send only 4 byte, for opcode, page address and
+ * Send a generic command to dataflash memory.
+ * This function send only 4 byte: opcode, page address and
* byte address.
*/
-static void send_cmd(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode)
+static void send_cmd(KFileDataflash *fd, dataflash_page_t page_addr, dataflash_offset_t byte_addr, DataFlashOpcode opcode)
{
/*
* Make sure to toggle CS signal in order,
* and reset dataflash command decoder.
- *
- * \note This is equivalent to CS_DISABLE() immediately followed by CS_ENABLE()
*/
- CS_TOGGLE();
+ CS_TOGGLE(fd);
/*
/*
* Send opcode.
*/
- spi_sendRecv(opcode);
+ kfile_putc(opcode, fd->channel);
/*
* Send page address.
*/
- spi_sendRecv((uint8_t)(page_addr >> (16 - DATAFLASH_PAGE_ADDRESS_BIT)));
- spi_sendRecv((uint8_t)((page_addr << (DATAFLASH_PAGE_ADDRESS_BIT - 8)) + (byte_addr >> 8)));
+ kfile_putc((uint8_t)(page_addr >> (16 - mem_info[fd->dev].page_bits)), fd->channel);
+ kfile_putc((uint8_t)((page_addr << (mem_info[fd->dev].page_bits - 8)) + (byte_addr >> 8)), fd->channel);
/*
* Send byte page address.
*/
- spi_sendRecv((uint8_t)byte_addr);
-
-
+ kfile_putc((uint8_t)byte_addr, fd->channel);
}
/**
* Reset dataflash memory function.
*
- * This function reset data flash memory
+ * If \a fd->setReset function is not NULL,
+ * this function resets data flash memory
* with one pulse reset long about 10usec.
*
*/
-static void dataflash_reset(void)
-{
- CS_ENABLE();
- RESET_ENABLE();
- timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH));
- CS_DISABLE();
- RESET_DISABLE();
- timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH));
-}
-
-/**
- * dataflash init function.
- * This function initialize a micro pin and
- * SPI driver, and test if data flash memory
- * density is the same wich define in dataflash.h.
- */
-MOD_DEFINE(dataflash);
-static bool dataflash_pin_init(void)
+static void dataflash_reset(KFileDataflash *fd)
{
- uint8_t stat;
-
- MOD_CHECK(spi);
-
- RESET_DISABLE();
- WRITE_ENABLE(); //pilot wp pin.
-
- RESET_OUT();
- WP_OUT();
-
- dataflash_reset();
-
- stat = dataflash_stat();
-
- MOD_INIT(dataflash);
-
- /*
- * 2,3,4,5 bits of 1 byte status register
- * indicate a device density of dataflash memory
- * (see datasheet for more detail.)
- */
- GET_ID_DESITY_DEVICE(stat);
-
- if(stat == DATAFLASH_ID_DEVICE_DENSITY)
- return true;
- else
- return false;
+ fd->setCS(false);
+ if (fd->setReset)
+ {
+ fd->setReset(true);
+ timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH));
+ fd->setReset(false);
+ timer_delayHp(us_to_hptime(RESET_PULSE_WIDTH));
+ }
}
/**
* Read status register of dataflah memory.
- *
*/
-static uint8_t dataflash_stat(void)
+static uint8_t dataflash_stat(KFileDataflash *fd)
{
- uint8_t stat;
-
/*
- * Make sure to toggle CS signal in order,
+ * Make sure to toggle CS signal
* and reset dataflash command decoder.
*/
- CS_TOGGLE();
+ CS_TOGGLE(fd);
- stat = spi_sendRecv(DFO_READ_STATUS);
- stat = spi_sendRecv(0x00);
+ kfile_putc(DFO_READ_STATUS, fd->channel);
- /*
- * Note: this function could be call one more time
- * to check register status (es. check if memory has been
- * teminate one operation), and so we don't disable CS to
- * allow fast reading of register status.
- */
- return stat;
+ return kfile_getc(fd->channel);
}
* return status register value.
*
*/
-static uint8_t dataflash_cmd(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode)
+static uint8_t dataflash_cmd(KFileDataflash *fd, dataflash_page_t page_addr, dataflash_offset_t byte_addr, DataFlashOpcode opcode)
{
-
uint8_t stat;
- send_cmd(page_addr, byte_addr, opcode);
+ send_cmd(fd, page_addr, byte_addr, opcode);
- CS_TOGGLE();
+ CS_TOGGLE(fd);
/*
* We chech data flash memory state, and wait until busy-flag
- * is hight.
+ * is high.
*/
- while(!(dataflash_stat() & BUSY_BIT));
+ while (!(dataflash_stat(fd) & BUSY_BIT))
+ {
+ #if CONFIG_KERNEL
+ proc_switch();
+ #endif
+ }
- stat = dataflash_stat();
+ stat = dataflash_stat(fd);
+ kfile_flush(fd->channel); // Flush channel
/*
* Data flash has completed a bus cycle, so disable CS.
*/
- CS_DISABLE();
-
- return (stat);
-
-}
-
-/**
- * Read one byte from main data flash memory or buffer data
- * flash memory.
- */
-static uint8_t dataflash_read_byte(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode)
-{
- uint8_t data;
+ fd->setCS(false);
- send_cmd(page_addr, byte_addr, opcode);
-
-#if CONFIG_DATA_FLASH == DATAFLASH_AT45DB041B
- if(opcode == DFO_READ_FLASH_MEM_BYTE)
- {
- /*
- * Send 24 don't care bit.
- */
- spi_sendRecv(0x00);
- spi_sendRecv(0x00);
- spi_sendRecv(0x00);
-
- }
-#endif
-
- spi_sendRecv(0x00); //Send 8 don't care bit.
- data = spi_sendRecv(0x00); //Read byte.
-
- CS_DISABLE();
-
- return data;
+ return stat;
}
/**
* Read \a len bytes from main data flash memory or buffer data
* flash memory, and put it in \a *block.
*/
-static void dataflash_read_block(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode, uint8_t *block, dataflashSize_t len)
+static void dataflash_readBlock(KFileDataflash *fd, dataflash_page_t page_addr, dataflash_offset_t byte_addr, DataFlashOpcode opcode, uint8_t *block, dataflash_size_t len)
{
+ send_cmd(fd, page_addr, byte_addr, opcode);
- send_cmd(page_addr, byte_addr, opcode);
-
- if(opcode == DFO_READ_FLASH_MEM_BYTE)
+ if (opcode == DFO_READ_FLASH_MEM_BYTE_B)
{
/*
- * Send 24 don't care bit.
+ * Send 24 don't care bits.
*/
- spi_sendRecv(0x00);
- spi_sendRecv(0x00);
- spi_sendRecv(0x00);
-
+ uint8_t dummy[] = { 0, 0, 0 };
+ kfile_write(fd->channel, dummy, sizeof(dummy));
}
- spi_sendRecv(0x00); //Send 8 don't care bit.
- spi_read(block, len); //Read len bytes ad put in block buffer.
-
-
- CS_DISABLE();
-
+ kfile_putc(0, fd->channel); //Send 8 don't care bit.
+ kfile_read(fd->channel, block, len); //Read len bytes ad put in block buffer.
+ kfile_flush(fd->channel); // Flush channel
+ fd->setCS(false);
}
/**
- * Write \a len bytes in buffer buffer data flash memory.
+ * Write \a len bytes in dataflash memory buffer.
*
- * \note Isn't possible to write bytes directly in main memory data
- * flash. To perform write in main memory you must before write in buffer
- * data flash memory, an then send command to write page in main memory.
+ * \note Is not possible to write directly in dataflash main memory.
+ * To perform a write in main memory you must first write in dataflash buffer
+ * memory and then send a command to write the page in main memory.
*/
-static void dataflash_write_block(dataflashOffset_t byte_addr, DataFlashOpcode opcode, uint8_t *block, dataflashSize_t len)
+static void dataflash_writeBlock(KFileDataflash *fd, dataflash_offset_t offset, DataFlashOpcode opcode, const uint8_t *block, dataflash_size_t len)
{
+ ASSERT(offset + len <= mem_info[fd->dev].page_size);
- send_cmd(0x00, byte_addr, opcode);
-
- spi_write(block, len); //Write len bytes.
+ send_cmd(fd, 0x00, offset, opcode);
- CS_DISABLE();
+ kfile_write(fd->channel, block, len); //Write len bytes.
+ kfile_flush(fd->channel); // Flush channel
+ fd->setCS(false);
}
/**
* Load selct page from dataflash memory to buffer.
*/
-static void dataflash_loadPage(dataflash_t page_addr)
+static void dataflash_loadPage(KFileDataflash *fd, dataflash_page_t page_addr)
{
- dataflash_cmd(page_addr, 0x00, DFO_MOV_MEM_TO_BUFF1);
+ dataflash_cmd(fd, page_addr, 0x00, DFO_MOV_MEM_TO_BUFF1);
}
/**
* Flush select page (stored in buffer) in data flash main memory page.
*/
-void dataflash_flush(void)
+static int dataflash_flush(KFile *_fd)
{
- if (page_modified)
+ KFileDataflash *fd = KFILEDATAFLASH(_fd);
+ if (fd->page_dirty)
{
- dataflash_cmd(previous_page, 0x00, DFO_WRITE_BUFF1_TO_MEM_E);
+ dataflash_cmd(fd, fd->current_page, 0x00, DFO_WRITE_BUFF1_TO_MEM_E);
- page_modified = false;
+ fd->page_dirty = false;
- kprintf("\n::=> Flush page:... <%ld>\n", previous_page);
+ kprintf("Flushing page <%ld>\n", fd->current_page);
}
+ return 0;
}
/* Kfile interface section */
/**
- * Open data flash file \a fd
- * \a name and \a mode are unused, cause flash memory is
- * threated like one file.
+ * Close file \a fd.
*/
-static bool dataflash_open(struct _KFile *fd, UNUSED_ARG(const char *, name), UNUSED_ARG(int, mode))
+static int dataflash_close(struct KFile *_fd)
{
- MOD_CHECK(dataflash);
-
- previous_page = 0;
- fd->seek_pos = 0;
- fd->size = (dataflashAddr_t)DATAFLASH_PAGE_SIZE * (dataflashAddr_t)DATAFLASH_NUM_PAGE;
-
- /* Load select page memory from data flash memory*/
- dataflash_loadPage(previous_page);
-
- kprintf("dataflash file opened\n");
- return true;
-}
-
-/**
- * Close file \a fd
- */
-static bool dataflash_close(UNUSED_ARG(struct _KFile *,fd))
-{
- dataflash_flush();
- kprintf("dataflash file closed\n");
- return true;
+ dataflash_flush(_fd);
+ TRACE;
+ return 0;
}
/**
- * Move \a fd file seek position of \a offset bytes
- * from current position.
+ * Reopen dataflash file \a fd.
*/
-static int32_t dataflash_seek(struct _KFile *fd, kfile_off_t offset, KSeekMode whence)
+static KFile *dataflash_reopen(KFile *_fd)
{
- uint32_t seek_pos;
+ KFileDataflash *fd = KFILEDATAFLASH(_fd);
+ dataflash_close(_fd);
- switch(whence)
- {
+ fd->current_page = 0;
+ fd->fd.seek_pos = 0;
- case KSM_SEEK_SET:
- seek_pos = 0;
- break;
- case KSM_SEEK_END:
- seek_pos = fd->size - 1;
- break;
- case KSM_SEEK_CUR:
- seek_pos = fd->seek_pos;
- break;
- default:
- ASSERT(0);
- return -1;
- break;
+ /* Load selected page from dataflash memory */
+ dataflash_loadPage(fd, fd->current_page);
- }
-
- /* Bound check */
- if (seek_pos + offset > fd->size)
- {
- ASSERT(0);
- return -1;
- }
-
- fd->seek_pos = seek_pos + offset;
- kprintf("Flash seek to [%u]\n", fd->seek_pos);
-
- return fd->seek_pos;
+ TRACE;
+ return &fd->fd;
}
+
/**
- * Read \a _buf lenght \a size byte from data flash memmory.
+ * Read in \a buf \a size bytes from dataflash memmory.
*
- * \note For read in data flash memory, we
- * check flag page_modified, if is true (that mean
- * we had been written a byte in buffer memory) we
- * flush current page in data flash main memory, and
- * then read byte from memory, else we read byte
+ * \note For reading data flash memory, we
+ * check flag page_dirty, if is true (that mean
+ * we have written a byte in buffer memory) we
+ * flush current page in main memory and
+ * then read from memory, else we read byte
* directly from data flash main memory.
*
* \return the number of bytes read.
*/
-static size_t dataflash_read(struct _KFile *fd, void *buf, size_t size)
+static size_t dataflash_read(struct KFile *_fd, void *buf, size_t size)
{
- dataflashOffset_t byte_addr;
- dataflashAddr_t page_addr;
- uin8_t *data = (uint8_t *)buf;
+ KFileDataflash *fd = KFILEDATAFLASH(_fd);
+ dataflash_offset_t byte_addr;
+ dataflash_page_t page_addr;
+ uint8_t *data = (uint8_t *)buf;
- ASSERT(fd->seek_pos + size <= fd->size);
- size = MIN((uint32_t)size, fd->size - fd->seek_pos);
- kprintf("Reading at pos[%u]\n", fd->seek_pos);
+ ASSERT(fd->fd.seek_pos + size <= fd->fd.size);
+ size = MIN((uint32_t)size, fd->fd.size - fd->fd.seek_pos);
+
+ kprintf("Reading at pos[%lu]\n", fd->fd.seek_pos);
/*
* We select page and offest from absolute address.
*/
- page_addr = fd->seek_pos / (dataflashAddr_t)DATAFLASH_PAGE_SIZE;
- byte_addr = fd->seek_pos % (dataflashOffset_t)DATAFLASH_PAGE_SIZE;
-
+ page_addr = fd->fd.seek_pos / mem_info[fd->dev].page_size;
+ byte_addr = fd->fd.seek_pos % mem_info[fd->dev].page_size;
- kprintf(" [page-<%ld>, byte-<%ld>]", page_addr, byte_addr);
+ kprintf("[page-<%ld>, byte-<%ld>]", page_addr, byte_addr);
/*
* Flush current page in main memory if
* we had been written a byte in memory
*/
- dataflash_flush();
+ dataflash_flush(&fd->fd);
/*
* Read byte in main page data flash memory.
*/
- dataflash_read_block(page_addr, byte_addr, DFO_READ_FLASH_MEM_BYTE, data, size);
+ dataflash_readBlock(fd, page_addr, byte_addr, mem_info[fd->dev].read_cmd, data, size);
- fd->seek_pos += size;
- kprintf(" ::=> Read data: %02x\n",data);
+ fd->fd.seek_pos += size;
+ kprintf("Read %ld bytes\n", size);
return size;
}
/**
- * Write \a _buf in data flash memory
+ * Write \a _buf in dataflash memory
*
- * \note For write \a _buf in data flash memory, we must
- * before write in buffer data flash memory, and at end of write,
- * we put page in data flash main memory. If we write in two
- * different page, we put in main memory current page and reload
- * page witch we want write.
+ * \note For writing \a _buf in dataflash memory, we must
+ * first write in buffer data flash memory. At the end of write,
+ * we can put page in dataflash main memory.
+ * If we write in two contiguous pages, we put in main memory current
+ * page and then reload the page which we want to write.
*
* \return the number of bytes write.
*/
-static size_t dataflash_write(struct _KFile *fd, const void *_buf, size_t size)
+static size_t dataflash_write(struct KFile *_fd, const void *_buf, size_t size)
{
+ KFileDataflash *fd = KFILEDATAFLASH(_fd);
- dataflashOffset_t byte_addr;
- dataflashAddr_t current_page;
+ dataflash_offset_t offset;
+ dataflash_page_t new_page;
+ size_t total_write = 0;
- uint8_t *data = (uint8_t *) _buf;
+ const uint8_t *data = (const uint8_t *) _buf;
- ASSERT(fd->seek_pos + size <= fd->size);
- size = MIN((uint32_t)size, fd->size - fd->seek_pos);
+ ASSERT(fd->fd.seek_pos + size <= fd->fd.size);
+ size = MIN((uint32_t)size, fd->fd.size - fd->fd.seek_pos);
- kprintf("Writing at pos[%u]\n", fd->seek_pos);
+ kprintf("Writing at pos[%lu]\n", fd->fd.seek_pos);
while (size)
{
/*
* We select page and offest from absolute address.
*/
- current_page = fd->seek_pos / (dataflashAddr_t)DATAFLASH_PAGE_SIZE;
- byte_addr = fd->seek_pos % (dataflashOffset_t)DATAFLASH_PAGE_SIZE;
+ new_page = fd->fd.seek_pos / mem_info[fd->dev].page_size;
+ offset = fd->fd.seek_pos % mem_info[fd->dev].page_size;
- size_t wr_len = MIN(size, DATAFLASH_PAGE_SIZE - byte_addr);
+ size_t wr_len = MIN(size, mem_info[fd->dev].page_size - offset);
- kprintf(" [page-<%ld>, byte-<%ld>]",current_page, byte_addr);
+ kprintf(" [page-<%ld>, byte-<%ld>]",new_page, offset);
- if (current_page != previous_page)
+ if (new_page != fd->current_page)
{
/* Flush current page in main memory*/
- dataflash_flush();
+ dataflash_flush(&fd->fd);
/* Load select page memory from data flash memory*/
- dataflash_loadPage(current_page);
+ dataflash_loadPage(fd, new_page);
- previous_page = current_page;
- kprintf(" >> Load page: <%ld> ",current_page);
+ fd->current_page = new_page;
+ kprintf(" >> Load page: <%ld> ", new_page);
}
/*
* Write byte in current page, and set true
- * page_modified flag.
+ * page_dirty flag.
*/
- dataflash_write_byte(byte_addr, DFO_WRITE_BUFF1, data);
- page_modified = true;
-
+ dataflash_writeBlock(fd, offset, DFO_WRITE_BUFF1, data, wr_len);
+ fd->page_dirty = true;
data += wr_len;
- fd->seek_pos += wr_len;
+ fd->fd.seek_pos += wr_len;
size -= wr_len;
total_write += wr_len;
}
- kprintf("written %u bytes\n", total_write);
+ kprintf("written %lu bytes\n", total_write);
return total_write;
}
-/**
- * Init data flash memory interface.
- */
-void dataflash_init(struct _KFile *fd)
-{
- // Set up data flash programming functions.
- fd->open = dataflash_open;
- fd->close = dataflash_close;
- fd->read = dataflash_read;
- fd->write = dataflash_write;
- fd->seek = dataflash_seek;
-
- // Init data flash memory and micro pin.
- ASSERT(dataflash_pin_init());
-}
+MOD_DEFINE(dataflash);
/**
- * Test function for dataflash.
- *
- * This function test check low level driver for
- * AT45xx (see dataflash.h for more info) data flash memory.
- * We write a string in memory in some page ad read it.
+ * Dataflash init function.
+ * This function initialize \a fd with SPI channel \a ch and test if data flash memory
+ * density is the same specified by device \a dev.
+ * \a setCS is a callback used to set/reset CS line.
+ * \a setReset is a callback used to set/reset the dataflash (can be NULL if reset is unconnected)
+ * \return true if ok, false if memory density read from dataflash is not compliant with the
+ * configured one.
*/
-void dataflash_test(void)
+bool dataflash_init(KFileDataflash *fd, KFile *ch, DataflashType dev, dataflash_setCS_t *setCS, dataflash_setReset_t *setReset)
{
- KFile fd;
-
- dataflash_init(&fd);
-
- uint8_t test_buf[] = "0123456789 Develer s.r.l.";
- uint8_t cmp_buf[];
-
- int tb_len = sizeof(test_buf);
- int tmp_len = 0;
-
- kprintf("\n======= Data Flash test function =========================================\n");
- kprintf("\nThe string test is: %s\n\n", test_buf);
-
- fd.open(&fd, NULL, 0);
-
- /* TEST 1 */
-
- // Seek to addr 0
- if (!fd.seek(&fd, 0, SEEK_SET))
- goto dataflash_test_end;
-
- // Test flash write to address 0 (page 0)
- tmp_len = fd->write(&fd, test_buf, len_tb)
- if (len_tb != tmp_len)
- {
- kprintf("Test 1: Wrong numer write bytes! expecteded [%d], write [%d]\n", tb_len, tmp_len);
- goto dataflash_test_end;
- }
-
- // Seek to addr 0
- if (fd.seek(&fd, 0, SEEK_SET) != 0)
- goto dataflash_test_end;
- tmp_len = 0;
-
- // Test flash read to address 0 (page 0)
- tmp_len = fd->read(&fd, cmp_buf, len_tb);
- if (len_tb != tmp_len)
- {
- kprintf("Test 1: Wrong numer read bytes! expecteded [%d], read [%d]\n", tb_len, tmp_len);
- goto dataflash_test_end;
- }
-
- // Compare if they are equal
- if ((memcmp(cmp_buf,test_buf, len_tb) == 0)
- {
- kprintf("Test 1: Readed test buf don't much!\n");
- goto dataflash_test_end;
- }
-
- /* TEST 2 */
+ uint8_t stat;
- // Go to middle address memory.
- if (!fd.seek(&fd, (((dataflashAddr_t)DFLASH_PAGE_SIZE * (dataflashAddr_t)DFLASH_NUM_PAGE) / 2), SEEK_CUR))
- goto dataflash_test_end;
- tmp_len = 0;
+ MOD_CHECK(dataflash_hw);
- // Test flash write at the middle of memory
- tmp_len = fd->write(&fd, test_buf, len_tb);
- if (len_tb != tmp_len)
- {
- kprintf("Test 2: Wrong numer write bytes! expecteded [%d], write [%d]\n", tb_len, tmp_len);
- goto dataflash_test_end;
- }
+ ASSERT(fd);
+ ASSERT(ch);
+ ASSERT(setCS);
+ ASSERT(dev < DFT_CNT);
- // Go to middle address memory.
- if (!fd.seek(&fd, (((dataflashAddr_t)DFLASH_PAGE_SIZE * (dataflashAddr_t)DFLASH_NUM_PAGE) / 2), SEEK_CUR))
- goto dataflash_test_end;
- tmp_len = 0;
+ memset(fd, 0, sizeof(*fd));
+ DB(fd->fd._type = KFT_DATAFLASH);
+ fd->dev = dev;
+ fd->channel = ch;
+ fd->setReset = setReset;
+ fd->setCS = setCS;
- // Test flash read at the middle of memory
- tmp_len = fd->read(&fd, cmp_buf, len_tb);
- if (len_tb != tmp_len)
- {
- kprintf("Test 2: Wrong numer read bytes! expecteded [%d], read [%d]\n", tb_len, tmp_len);
- goto dataflash_test_end;
- }
+ // Setup data flash programming functions.
+ fd->fd.reopen = dataflash_reopen;
+ fd->fd.close = dataflash_close;
+ fd->fd.read = dataflash_read;
+ fd->fd.write = dataflash_write;
+ fd->fd.seek = kfile_genericSeek;
+ fd->fd.flush = dataflash_flush;
- // Compare if they are equal
- if ((memcmp(cmp_buf,test_buf, len_tb) == 0)
- {
- kprintf("Test 2: Readed test buf don't much!\n");
- goto dataflash_test_end;
- }
- /* TEST 3 */
+ dataflash_reset(fd);
- // Go to end of data flash.
- if(!fd.seek(&fd, ((dataflashAddr_t)DFLASH_PAGE_SIZE * (dataflashAddr_t)DFLASH_NUM_PAGE) - len_tb, SEEK_END));
- goto dataflash_test_end;
- tmp_len = 0;
+ stat = dataflash_stat(fd);
- // Test flash write at the end of memory
- tmp_len = fd->write(&fd, test_buf, len_tb);
- if (len_tb != tmp_len)
- {
- kprintf("Test 3: Wrong numer write bytes! expecteded [%d], write [%d]\n", tb_len, tmp_len);
- goto dataflash_test_end;
- }
-
- // Go to end of data flash.
- if(!fd.seek(&fd, ((dataflashAddr_t)DFLASH_PAGE_SIZE * (dataflashAddr_t)DFLASH_NUM_PAGE) - len_tb, SEEK_END));
- goto dataflash_test_end;
- tmp_len = 0
-
- // Test flash read at the end of memory
- tmp_len = fd->read(&fd, cmp_buf, len_tb);
- if (len_tb != tmp_len)
- {
- kprintf("Test 3: Wrong numer read bytes! expecteded [%d], read [%d]\n", tb_len, tmp_len);
- goto dataflash_test_end;
- }
-
- // Compare if they are equal
- if ((memcmp(cmp_buf,test_buf, len_tb) == 0)
- {
- kprintf("Test 3: Readed test buf don't much!\n");
- goto dataflash_test_end;
- }
+ /*
+ * 2,3,4,5 bits of 1 byte status register
+ * indicate a device density of dataflash memory
+ * (see datasheet for more detail.)
+ */
+ if (GET_ID_DESITY_DEVICE(stat) != mem_info[fd->dev].density_id)
+ return false;
- kprintf("\n");
+ fd->current_page = 0;
+ fd->fd.seek_pos = 0;
+ fd->fd.size = mem_info[fd->dev].page_size * mem_info[fd->dev].page_cnt;
- kprintf("\n====== Test end ===========================================================\n");
- fd.close(&fd);
+ /* Load selected page from dataflash memory */
+ dataflash_loadPage(fd, fd->current_page);
+ MOD_INIT(dataflash);
return true;
-
-dataflash_test_end:
- fd.close(&fd);
- return false;
-
}
-