First refactor to kblock.
authorasterix <asterix@38d2e660-2303-0410-9eaa-f027e97ec537>
Fri, 13 Aug 2010 13:09:58 +0000 (13:09 +0000)
committerasterix <asterix@38d2e660-2303-0410-9eaa-f027e97ec537>
Fri, 13 Aug 2010 13:09:58 +0000 (13:09 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4185 38d2e660-2303-0410-9eaa-f027e97ec537

bertos/cpu/arm/drv/flash_lpc2.c
bertos/cpu/arm/drv/flash_lpc2.h

index f3c60f1fd28a763f59e1620615e6cd00176786a4..ca9843327c2cee9bda4befaf6827b42ddaa370e8 100644 (file)
@@ -48,9 +48,9 @@
 #include <cpu/irq.h>
 #include <cpu/attr.h>
 #include <cpu/power.h>
+#include <cpu/types.h>
 
-#include <kern/kfile.h>
-
+#include <io/kblock.h>
 #include <io/arm.h>
 
 #include <drv/timer.h>
 
 #include <string.h>
 
+#define CMD_SUCCESS 0
 
-#define IAP_ADDRESS 0x7ffffff1
-
-typedef enum IapCommands
+struct FlashHardware
 {
-       PREPARE_SECTOR_FOR_WRITE = 50,
-       COPY_RAM_TO_FLASH = 51,
-       ERASE_SECTOR = 52,
-       BLANK_CHECK_SECTOR = 53,
-       READ_PART_ID = 54,
-       READ_BOOT_VER = 55,
-       COMPARE = 56,
-       REINVOKE_ISP = 57,
-} IapCommands;
-
-
-#define CMD_SUCCESS 0
+       uint8_t status;
+};
 
 typedef struct IapCmd
 {
@@ -90,13 +79,9 @@ typedef struct IapRes
 
 typedef void (*iap_callback_t)(IapCmd *, IapRes *);
 
-iap_callback_t iap=(iap_callback_t)IAP_ADDRESS;
-
-#define FLASH_MEM_SIZE (504 * 1024L)
-
-static size_t flash_start_addr;
+iap_callback_t iap = (iap_callback_t)IAP_ADDRESS;
 
-static size_t sector_size(page_t page)
+static size_t sector_size(uint32_t page)
 {
        if (page < 8)
                return 4096;
@@ -109,7 +94,7 @@ static size_t sector_size(page_t page)
        return 0;
 }
 
-static size_t sector_addr(page_t page)
+static size_t sector_addr(uint32_t page)
 {
        if (page < 8)
                return page * 4096;
@@ -123,7 +108,7 @@ static size_t sector_addr(page_t page)
 }
 
 
-static page_t addr_to_sector(size_t addr)
+static uint32_t addr_to_sector(size_t addr)
 {
        if (addr < 4096 * 8)
                return addr / 4096;
@@ -136,7 +121,7 @@ static page_t addr_to_sector(size_t addr)
        return 0;
 }
 
-static page_addr_t addr_to_pageaddr(size_t addr)
+static uint32_t addr_to_pageaddr(size_t addr)
 {
        if (addr < 4096 * 8)
                return addr % 4096;
@@ -149,53 +134,69 @@ static page_addr_t addr_to_pageaddr(size_t addr)
        return 0;
 }
 
+static size_t lpc2_flash_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size)
+{
+       ASSERT(offset == 0);
+       ASSERT(size == blk->blk_size);
 
-static uint32_t page_buf[1024];//MAX_FLASH_PAGE_SIZE / sizeof(uint32_t)];
-static bool page_dirty;
-static page_t curr_page;
+       ASSERT(sector_size(idx) <= FLASH_PAGE_SIZE_BYTES);
 
-/**
- * Send write command.
- *
- * After WR command cpu write bufferd page into flash memory.
- *
- */
-static void flash_lpc2_writePage(page_t page, uint32_t *buf)
+       memcpy(buf, (void *)(idx * blk->blk_size), size);
+       return size;
+}
+
+static size_t lpc2_flash_writeDirect(struct KBlock *blk, block_idx_t idx, const void *_buf, size_t offset, size_t size)
 {
+       ASSERT(offset == 0);
+       ASSERT(size == blk->blk_size);
+       ASSERT(sector_size(idx) <= FLASH_PAGE_SIZE_BYTES);
+
+       Flash *fls = FLASH_CAST(blk);
+       const uint8_t *buf = (const uint8_t *)_buf;
        cpu_flags_t flags;
 
        //Compute page address of current page.
-       page_addr_t addr = sector_addr(page);
+       uint32_t addr = sector_addr(idx);
 
-       LOG_INFO("Writing page %ld...\n", page);
+       LOG_INFO("Writing page %ld...\n", idx);
 
        IRQ_SAVE_DISABLE(flags);
 
        IapCmd cmd;
        IapRes res;
        cmd.cmd = PREPARE_SECTOR_FOR_WRITE;
-       cmd.param[0] = cmd.param[1] = page;
+       cmd.param[0] = cmd.param[1] = idx;
        iap(&cmd, &res);
        if (res.status != CMD_SUCCESS)
+       {
                LOG_ERR("%ld\n", res.status);
+               fls->hw->status |= FLASH_WR_ERR;
+               return 0;
+       }
 
        cmd.cmd = ERASE_SECTOR;
-       cmd.param[0] = cmd.param[1] = page;
+       cmd.param[0] = cmd.param[1] = idx;
        cmd.param[2] = CPU_FREQ / 1000;
        iap(&cmd, &res);
        if (res.status != CMD_SUCCESS)
+       {
                LOG_ERR("%ld\n", res.status);
-
-       size_t size = sector_size(page);
+               fls->hw->status |= FLASH_WR_ERR;
+               return 0;
+       }
 
        while (size)
        {
-               LOG_INFO("Writing page %ld, addr %ld, size %d\n", page, addr, size);
+               LOG_INFO("Writing page %ld, addr %ld, size %d\n", idx, addr, size);
                cmd.cmd = PREPARE_SECTOR_FOR_WRITE;
-               cmd.param[0] = cmd.param[1] = page;
+               cmd.param[0] = cmd.param[1] = idx;
                iap(&cmd, &res);
                if (res.status != CMD_SUCCESS)
+               {
                        LOG_ERR("%ld\n", res.status);
+                       fls->hw->status |= FLASH_WR_ERR;
+                       return 0;
+               }
 
                cmd.cmd = COPY_RAM_TO_FLASH;
                cmd.param[0] = addr;
@@ -204,7 +205,11 @@ static void flash_lpc2_writePage(page_t page, uint32_t *buf)
                cmd.param[3] = CPU_FREQ / 1000;
                iap(&cmd, &res);
                if (res.status != CMD_SUCCESS)
+               {
                        LOG_ERR("%ld\n", res.status);
+                       fls->hw->status |= FLASH_WR_ERR;
+                       return 0;
+               }
 
                size -= 4096;
                addr += 4096;
@@ -213,155 +218,79 @@ static void flash_lpc2_writePage(page_t page, uint32_t *buf)
 
        IRQ_RESTORE(flags);
        LOG_INFO("Done\n");
+
+       return blk->blk_size;
 }
 
-/**
- * Write modified page on internal latch, and then send write command to
- * flush page to internal flash.
- */
-static int flash_lpc2_flush(UNUSED_ARG(KFile *, _fd))
+static int lpc2_flash_error(struct KBlock *blk)
 {
-       if (page_dirty)
-       {
-               flash_lpc2_writePage(curr_page, page_buf);
-               page_dirty = false;
-       }
-       return 0;
+       Flash *fls = FLASH_CAST(blk);
+       return fls->hw->status;
 }
 
-
-/**
- * Check current page and if \a page is different, load it in
- * temporary buffer.
- */
-static void flash_lpc2_loadPage(KFile *fd, page_t page)
+static void lpc2_flash_clearerror(struct KBlock *blk)
 {
-       if (page != curr_page)
-       {
-               flash_lpc2_flush(fd);
-
-               size_t addr = sector_addr(page);
-               size_t size = sector_size(page);
-               LOG_INFO("page %ld, addr %d, size %d\n", page, addr, size);
-               // Load page
-               memcpy(page_buf, (char *)addr, size);
-               curr_page = page;
-               LOG_INFO("Loaded page %lu\n", curr_page);
-       }
+       Flash *fls = FLASH_CAST(blk);
+       fls->hw->status = 0;
 }
 
-/**
- * Write program memory.
- * Write \a size bytes from buffer \a _buf to file \a fd
- * \note Write operations are buffered.
- */
-static size_t flash_lpc2_write(struct KFile *fd, const void *_buf, size_t size)
+static const KBlockVTable flash_lpc2_buffered_vt =
 {
-       const uint8_t *buf =(const uint8_t *)_buf;
+       .readDirect = lpc2_flash_readDirect,
+       .writeDirect = lpc2_flash_writeDirect,
 
-       page_t page;
-       page_addr_t page_addr;
-       size_t total_write = 0;
+       .readBuf = kblock_swReadBuf,
+       .writeBuf = kblock_swWriteBuf,
+       .load = kblock_swLoad,
+       .store = kblock_swStore,
 
-       size = MIN((kfile_off_t)size, fd->size - fd->seek_pos);
+       .close = kblock_swClose,
 
-       LOG_INFO("Writing at pos[%lu]\n", fd->seek_pos);
-       while (size)
-       {
-               page = addr_to_sector(fd->seek_pos + flash_start_addr);
-               page_addr = addr_to_pageaddr(fd->seek_pos + flash_start_addr);
-               LOG_INFO("addr %ld, page %ld, page_addr %ld\n", fd->seek_pos + flash_start_addr, page, page_addr);
+       .error = lpc2_flash_error,
+       .clearerr = lpc2_flash_clearerror,
+};
 
-               flash_lpc2_loadPage(fd, page);
+static const KBlockVTable flash_lpc2_unbuffered_vt =
+{
+       .readDirect = lpc2_flash_readDirect,
+       .writeDirect = lpc2_flash_writeDirect,
 
-               size_t wr_len = MIN(size, (size_t)(sector_size(page) - page_addr));
+       .close = kblock_swClose,
 
-               memcpy(((uint8_t *)page_buf) + page_addr, buf, wr_len);
-               page_dirty = true;
+       .error = lpc2_flash_error,
+       .clearerr = lpc2_flash_clearerror,
+};
 
-               buf += wr_len;
-               fd->seek_pos += wr_len;
-               size -= wr_len;
-               total_write += wr_len;
-       }
-       LOG_INFO("written %u bytes\n", total_write);
-       return total_write;
-}
+static struct FlashHardware flash_lpc2_hw;
+static uint8_t flash_buf[FLASH_PAGE_SIZE_BYTES];
 
-/**
- * Open flash file \a fd
- * \a name and \a mode are unused, cause flash memory is
- * threated like one file.
- */
-static void flash_lpc2_open(struct FlashLpc2 *fd)
+static void common_init(Flash *fls)
 {
-       curr_page = addr_to_sector(FLASH_BOOT_SIZE);
-       if (addr_to_pageaddr(FLASH_BOOT_SIZE))
-               curr_page++;
-
-       flash_start_addr = sector_addr(curr_page);
-       LOG_INFO("Boot size %d, curr_page %ld, flash_start_addr %d\n", FLASH_BOOT_SIZE, curr_page, flash_start_addr);
-
-       fd->fd.size = FLASH_MEM_SIZE - sector_addr(curr_page);
-       fd->fd.seek_pos = 0;
+       memset(fls, 0, sizeof(*fls));
+       DB(fls->blk.priv.type = KBT_FLASH);
 
-       memcpy(page_buf, (char *)sector_addr(curr_page), sector_size(curr_page));
+       fls->hw = &flash_lpc2_hw;
 
-       page_dirty = false;
-       LOG_INFO("Flash file opened, pos %ld, size %ld\n", fd->fd.seek_pos, fd->fd.size);
+       fls->blk.blk_size = FLASH_PAGE_SIZE_BYTES;
+       fls->blk.blk_cnt = 28;
 }
 
-/**
- * Read from file \a fd \a size bytes and put it in buffer \a buf
- * \return the number of bytes read.
- */
-static size_t flash_lpc2_read(struct KFile *fd, void *_buf, size_t size)
+void flash_hw_init(Flash *fls)
 {
-       uint8_t *buf =(uint8_t *)_buf;
-
-       size = MIN((kfile_off_t)size, fd->size - fd->seek_pos);
-
-       LOG_INFO("Reading at pos[%lu]\n", fd->seek_pos);
-
-       // Flush current buffered page (if modified).
-       flash_lpc2_flush(fd);
-
-       kfile_off_t *addr = (kfile_off_t *)(fd->seek_pos + flash_start_addr);
-       LOG_INFO("actual addr %ld\n", (uint32_t)addr);
-       memcpy(buf, addr, size);
-
-       for (unsigned i = 0; i< size; i++)
-       {
-               if (i % 16 == 0)
-                       kputchar('\n');
-
-               kprintf("%02x ", buf[i]);
-       }
-       kputchar('\n');
+       common_init(fls);
+       fls->blk.priv.vt = &flash_lpc2_buffered_vt;
+       fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE;
+       fls->blk.priv.buf = flash_buf;
 
-       fd->seek_pos += size;
+       /* Load the first block in the cache */
+       void *flash_start = 0x0;
+       memcpy(fls->blk.priv.buf, flash_start, fls->blk.blk_size);
 
-       LOG_INFO("Read %u bytes\n", size);
-       return size;
+       kprintf("page[%d]\n", sector_addr(22));
 }
 
-
-/**
- * Init module to perform write and read operation on internal
- * flash memory.
- */
-void flash_hw_init(struct FlashLpc2 *fd)
+void flash_hw_initUnbuffered(Flash *fls)
 {
-       memset(fd, 0, sizeof(*fd));
-       // Init base class.
-       kfile_init(&fd->fd);
-       DB(fd->fd._type = KFT_FLASH);
-
-       // Set up flash programming functions.
-       fd->fd.write = flash_lpc2_write;
-       fd->fd.read = flash_lpc2_read;
-       fd->fd.flush = flash_lpc2_flush;
-
-       flash_lpc2_open(fd);
-       TRACE;
+       common_init(fls);
+       fls->blk.priv.vt = &flash_lpc2_unbuffered_vt;
 }
index 92c7df1ca017d4e16cf7e00b5579af390246a019..34eab97cab5709263076d42ad4d1d9696bf05143 100644 (file)
  * invalidate any other reasons why the executable file might be covered by
  * the GNU General Public License.
  *
- * Copyright 2009 Develer S.r.l. (http://www.develer.com/)
+ * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
  *
  * -->
  *
  * \author Daniele Basile <asterix@develer.com>
  *
- * \brief At91sam7 Internal flash read/write driver.
+ * \brief NPX lpc23xx embedded flash read/write driver.
  *
  *
  */