X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=drv%2Fdataflash.c;h=2f4f897ee0665133d6fb70f355fb722115d37efa;hb=1ab5fa0763879ab997884c8bc88631b69205a191;hp=4876e376889d1b3b42833d8a453ff20c6b8a99e9;hpb=fbec2cb9b7fbee7bac4c685d0581f17503e98269;p=bertos.git diff --git a/drv/dataflash.c b/drv/dataflash.c index 4876e376..2f4f897e 100644 --- a/drv/dataflash.c +++ b/drv/dataflash.c @@ -50,13 +50,13 @@ #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; /** @@ -64,7 +64,7 @@ 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) { /* @@ -88,7 +88,6 @@ static void send_cmd(dataflash_t page_addr, dataflash_t byte_addr, DFlashOpcode * hight part of address byte in third byte togheter low par of page * address. * - * \{ */ /* @@ -98,18 +97,15 @@ static void send_cmd(dataflash_t page_addr, dataflash_t byte_addr, DFlashOpcode /* * 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); - /* \} */ } @@ -181,13 +177,18 @@ static uint8_t dataflash_stat(void) /* * 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; } @@ -197,13 +198,14 @@ static uint8_t dataflash_stat(void) * 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 @@ -211,7 +213,14 @@ static uint8_t dataflash_cmd(dataflash_t page_addr, dataflash_t byte_addr, DFlas */ 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); } @@ -219,7 +228,7 @@ static uint8_t dataflash_cmd(dataflash_t page_addr, dataflash_t byte_addr, DFlas * 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; @@ -230,18 +239,17 @@ static uint8_t dataflash_read_byte(dataflash_t page_addr, dataflash_t byte_addr, { /* * 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; @@ -251,7 +259,7 @@ static uint8_t dataflash_read_byte(dataflash_t page_addr, dataflash_t byte_addr, * 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); @@ -260,12 +268,11 @@ static void dataflash_read_block(dataflash_t page_addr, dataflash_t byte_addr, D { /* * Send 24 don't care bit. - * \{ */ spi_sendRecv(0x00); spi_sendRecv(0x00); spi_sendRecv(0x00); - /* \} */ + } spi_sendRecv(0x00); //Send 8 don't care bit. @@ -284,7 +291,7 @@ static void dataflash_read_block(dataflash_t page_addr, dataflash_t byte_addr, D * 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); @@ -302,8 +309,6 @@ static void dataflash_write_block(dataflash_t byte_addr, DFlashOpcode opcode, ui static void dataflash_loadPage(dataflash_t page_addr) { dataflash_cmd(page_addr, 0x00, DFO_MOV_MEM_TO_BUFF1); - - CS_DISABLE(); } /** @@ -315,7 +320,6 @@ void dataflash_flush(void) { dataflash_cmd(previous_page, 0x00, DFO_WRITE_BUFF1_TO_MEM_E); - CS_DISABLE(); page_modified = false; kprintf("\n::=> Flush page:... <%ld>\n", previous_page); @@ -334,6 +338,8 @@ static bool dataflash_open(struct _KFile *fd, UNUSED_ARG(const char *, name), UN 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); @@ -356,34 +362,72 @@ static bool dataflash_close(UNUSED_ARG(struct _KFile *,fd)) * 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); @@ -396,20 +440,77 @@ static size_t dataflash_read(struct _KFile *fd, void *buf, size_t size) /* * 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; } /** @@ -426,4 +527,144 @@ void dataflash_init(struct _KFile *fd) // 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; + +} +