#include "hw_spi.h"
-
+#warning This driver must be test before use!
/**
* Global variable for store current and previous data
* flash memory page address during operation of writing.
*/
-dataflash_t previous_page = 0;
-bool page_modified = false;
+static dataflash_t previous_page = 0;
+static bool page_modified = false;
/**
* This function send only 4 byte, for opcode, page address and
* byte address.
*/
-static void send_cmd(dataflash_t page_addr, dataflash_t byte_addr, DFlashOpcode opcode)
+static void send_cmd(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode)
{
/*
* hight part of address byte in third byte togheter low par of page
* address.
*
- * \{
*/
/*
/*
* 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)));
- /*\}*/
/*
* Send byte page address.
*/
spi_sendRecv((uint8_t)byte_addr);
- /* \} */
}
/*
* Make sure to toggle CS signal in order,
* and reset dataflash command decoder.
- * \{
*/
CS_TOGGLE();
stat = spi_sendRecv(DFO_READ_STATUS);
stat = spi_sendRecv(0x00);
+ /*
+ * 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 status register value.
*
*/
-static uint8_t dataflash_cmd(dataflash_t page_addr, dataflash_t byte_addr, DFlashOpcode opcode)
+static uint8_t dataflash_cmd(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode)
{
+ uint8_t stat;
+
send_cmd(page_addr, byte_addr, opcode);
- CS_DISABLE();
- CS_ENABLE();
+ CS_TOGGLE();
/*
* We chech data flash memory state, and wait until busy-flag
*/
while(!(dataflash_stat() & BUSY_BIT));
- return (dataflash_stat());
+ stat = dataflash_stat();
+
+ /*
+ * 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, dataflash_t byte_addr, DFlashOpcode opcode)
+static uint8_t dataflash_read_byte(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode)
{
uint8_t data;
{
/*
* 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;
* 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, dataflash_t byte_addr, DFlashOpcode opcode, uint8_t *block, dataflashSize_t len)
+static void dataflash_read_block(dataflash_t page_addr, dataflashOffset_t byte_addr, DataFlashOpcode opcode, uint8_t *block, dataflashSize_t len)
{
send_cmd(page_addr, byte_addr, opcode);
{
/*
* Send 24 don't care bit.
- * \{
*/
spi_sendRecv(0x00);
spi_sendRecv(0x00);
spi_sendRecv(0x00);
- /* \} */
+
}
spi_sendRecv(0x00); //Send 8 don't care bit.
* 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.
*/
-static void dataflash_write_block(dataflash_t byte_addr, DFlashOpcode opcode, uint8_t *block, dataflashSize_t len)
+static void dataflash_write_block(dataflashOffset_t byte_addr, DataFlashOpcode opcode, uint8_t *block, dataflashSize_t len)
{
send_cmd(0x00, byte_addr, opcode);
static void dataflash_loadPage(dataflash_t page_addr)
{
dataflash_cmd(page_addr, 0x00, DFO_MOV_MEM_TO_BUFF1);
-
- CS_DISABLE();
}
/**
{
dataflash_cmd(previous_page, 0x00, DFO_WRITE_BUFF1_TO_MEM_E);
- CS_DISABLE();
page_modified = false;
kprintf("\n::=> Flush page:... <%ld>\n", previous_page);
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);
* Move \a fd file seek position of \a offset bytes
* from current position.
*/
-static int32_t dataflash_seek(struct _KFile *fd, int32_t offset, KSeekMode whence)
+static int32_t dataflash_seek(struct _KFile *fd, kfile_off_t offset, KSeekMode whence)
{
+ uint32_t seek_pos;
+
+ switch(whence)
+ {
+
+ 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;
+
+ }
+
+ /* 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;
}
/**
- * Read from file \a fd \a size bytes and put it in buffer \a buf
+ * Read \a _buf lenght \a size byte from data flash 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
+ * 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)
{
-
-//TODO:
-
- dataflashAddr_t byte_addr;
+ dataflashOffset_t byte_addr;
dataflashAddr_t page_addr;
+ uin8_t *data = (uint8_t *)buf;
- uint8_t data;
- kprintf(" Read at address:... %ld ",addr);
+ 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);
/*
- * We select from absolute address page address
- * and byte address in page.
- * \{
+ * We select page and offest from absolute address.
*/
- page_addr = addr / (dataflashAddr_t)DATAFLASH_PAGE_SIZE;
- byte_addr = addr % (dataflashAddr_t)DATAFLASH_PAGE_SIZE;
- /* \} */
+ page_addr = fd->seek_pos / (dataflashAddr_t)DATAFLASH_PAGE_SIZE;
+ byte_addr = fd->seek_pos % (dataflashOffset_t)DATAFLASH_PAGE_SIZE;
+
kprintf(" [page-<%ld>, byte-<%ld>]", page_addr, byte_addr);
/*
* Read byte in main page data flash memory.
*/
- data = dataflash_read_byte(page_addr, byte_addr, DFO_READ_FLASH_MEM_BYTE);
+ dataflash_read_block(page_addr, byte_addr, DFO_READ_FLASH_MEM_BYTE, data, size);
+ fd->seek_pos += size;
kprintf(" ::=> Read data: %02x\n",data);
- return data;
+ return size;
}
/**
- * Write program memory.
- * Write \a size bytes from buffer \a _buf to file \a fd
- * \note Write operations are buffered.
+ * Write \a _buf in data flash 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.
+ *
+ * \return the number of bytes write.
*/
static size_t dataflash_write(struct _KFile *fd, const void *_buf, size_t size)
{
+
+ dataflashOffset_t byte_addr;
+ dataflashAddr_t current_page;
+
+ uint8_t *data = (uint8_t *) _buf;
+
+ ASSERT(fd->seek_pos + size <= fd->size);
+ size = MIN((uint32_t)size, fd->size - fd->seek_pos);
+
+ kprintf("Writing at pos[%u]\n", 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;
+
+
+ size_t wr_len = MIN(size, DATAFLASH_PAGE_SIZE - byte_addr);
+
+ kprintf(" [page-<%ld>, byte-<%ld>]",current_page, byte_addr);
+
+ if (current_page != previous_page)
+ {
+ /* Flush current page in main memory*/
+ dataflash_flush();
+ /* Load select page memory from data flash memory*/
+ dataflash_loadPage(current_page);
+
+ previous_page = current_page;
+ kprintf(" >> Load page: <%ld> ",current_page);
+ }
+ /*
+ * Write byte in current page, and set true
+ * page_modified flag.
+ */
+ dataflash_write_byte(byte_addr, DFO_WRITE_BUFF1, data);
+ page_modified = true;
+
+
+ data += wr_len;
+ fd->seek_pos += wr_len;
+ size -= wr_len;
+ total_write += wr_len;
+ }
+
+ kprintf("written %u bytes\n", total_write);
+ return total_write;
}
/**
// Init data flash memory and micro pin.
ASSERT(dataflash_pin_init());
-}
\ No newline at end of file
+}
+
+/**
+ * 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.
+ */
+void dataflash_test(void)
+{
+ KFile fd;
+
+ dataflash_init(&fd);
+
+ uint8_t test_buf[] = "0123456789 Develer s.r.l.";
+ uint8_t cmp_buf[sizeof(test_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, KSM_SEEK_SET))
+ goto dataflash_test_end;
+
+ // Test flash write to address 0 (page 0)
+ tmp_len = fd.write(&fd, test_buf, tb_len);
+ if (tb_len != 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, KSM_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, tb_len);
+ if (tb_len != 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, tb_len) == 0))
+ {
+ kprintf("Test 1: Readed test buf don't much!\n");
+ goto dataflash_test_end;
+ }
+
+ /* TEST 2 */
+
+ // 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;
+
+ // Test flash write at the middle of memory
+ tmp_len = fd.write(&fd, test_buf, tb_len);
+ if (tb_len != tmp_len)
+ {
+ kprintf("Test 2: Wrong numer write bytes! expecteded [%d], write [%d]\n", tb_len, tmp_len);
+ goto dataflash_test_end;
+ }
+
+ // 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;
+
+ // Test flash read at the middle of memory
+ tmp_len = fd.read(&fd, cmp_buf, tb_len);
+ if (tb_len != tmp_len)
+ {
+ kprintf("Test 2: 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, tb_len) == 0))
+ {
+ kprintf("Test 2: Readed test buf don't much!\n");
+ goto dataflash_test_end;
+ }
+ /* TEST 3 */
+
+ // 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 write at the end of memory
+ tmp_len = fd.write(&fd, test_buf, tb_len);
+ if (tb_len != 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, tb_len);
+ if (tb_len != 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, tb_len) == 0))
+ {
+ kprintf("Test 3: Readed test buf don't much!\n");
+ goto dataflash_test_end;
+ }
+
+ kprintf("\n");
+
+ kprintf("\n====== Test end ===========================================================\n");
+ fd.close(&fd);
+ return true;
+
+dataflash_test_end:
+ fd.close(&fd);
+ return false;
+
+}
+