Some fixes. Implement close. Comply to new flash api.
authorasterix <asterix@38d2e660-2303-0410-9eaa-f027e97ec537>
Wed, 1 Sep 2010 11:00:58 +0000 (11:00 +0000)
committerasterix <asterix@38d2e660-2303-0410-9eaa-f027e97ec537>
Wed, 1 Sep 2010 11:00:58 +0000 (11:00 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4217 38d2e660-2303-0410-9eaa-f027e97ec537

bertos/cpu/arm/drv/flash_lpc2.c

index 21c514f7cd12db6e08f8e9eaff4e371da6459be2..99cf91e89a4ccb66beba63233d7348e29405cbf8 100644 (file)
@@ -58,6 +58,8 @@
 #include <drv/timer.h>
 #include <drv/flash.h>
 
+#include <struct/bitarray.h>
+
 #include <string.h>
 
 /* Embedded flash programming defines. */
@@ -77,8 +79,8 @@ typedef enum IapCommands
 
 #if CPU_ARM_LPC2378
        #define FLASH_MEM_SIZE         (504 * 1024L)
-       #define FLASH_PAGE_SIZE_BYTES   4096
-       #define FLASH_PAGE_4K_CNT         14
+       #define FLASH_PAGE_SIZE_BYTES          4096
+       #define FLASH_REAL_PAGE_CNT              28
 #else
        #error Unknown CPU
 #endif
@@ -90,6 +92,34 @@ struct FlashHardware
        uint8_t status;
 };
 
+#define FLASH_PAGE_CNT  FLASH_MEM_SIZE / FLASH_PAGE_SIZE_BYTES
+
+ALLOC_BITARRAY(page_dirty, FLASH_PAGE_CNT);
+
+uint8_t erase_group[] = {
+
+       4096 / FLASH_PAGE_SIZE_BYTES, 4096 / FLASH_PAGE_SIZE_BYTES,
+       4096 / FLASH_PAGE_SIZE_BYTES, 4096 / FLASH_PAGE_SIZE_BYTES,
+
+       4096 / FLASH_PAGE_SIZE_BYTES, 4096 / FLASH_PAGE_SIZE_BYTES,
+       4096 / FLASH_PAGE_SIZE_BYTES, 4096 / FLASH_PAGE_SIZE_BYTES,
+
+       32768 / FLASH_PAGE_SIZE_BYTES, 32768 / FLASH_PAGE_SIZE_BYTES,
+       32768 / FLASH_PAGE_SIZE_BYTES, 32768 / FLASH_PAGE_SIZE_BYTES,
+
+       32768 / FLASH_PAGE_SIZE_BYTES, 32768 / FLASH_PAGE_SIZE_BYTES,
+       32768 / FLASH_PAGE_SIZE_BYTES, 32768 / FLASH_PAGE_SIZE_BYTES,
+
+       32768 / FLASH_PAGE_SIZE_BYTES, 32768 / FLASH_PAGE_SIZE_BYTES,
+       32768 / FLASH_PAGE_SIZE_BYTES, 32768 / FLASH_PAGE_SIZE_BYTES,
+
+       32768 / FLASH_PAGE_SIZE_BYTES, 32768 / FLASH_PAGE_SIZE_BYTES,
+       4096 / FLASH_PAGE_SIZE_BYTES, 4096 / FLASH_PAGE_SIZE_BYTES,
+
+       4096 / FLASH_PAGE_SIZE_BYTES, 4096 / FLASH_PAGE_SIZE_BYTES,
+       4096 / FLASH_PAGE_SIZE_BYTES, 4096 / FLASH_PAGE_SIZE_BYTES,
+};
+
 typedef struct IapCmd
 {
        uint32_t cmd;
@@ -146,26 +176,11 @@ static uint32_t addr_to_sector(size_t addr)
        return 0;
 }
 
-static uint32_t addr_to_pageaddr(size_t addr)
-{
-       if (addr < 4096 * 8)
-               return addr % 4096;
-       else if (addr < 4096 * 8 + 32768L * 14)
-               return (addr - 4096 * 8) % 32768;
-       else if (addr < 4096 * 8 + 32768L * 14 + 4096 * 6)
-               return (addr - 4096 * 8 - 32768L * 14) % 4096;
-
-       ASSERT(0);
-       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);
 
-       ASSERT(sector_size(idx) <= FLASH_PAGE_SIZE_BYTES);
-
        memcpy(buf, (void *)(idx * blk->blk_size), size);
        return size;
 }
@@ -173,80 +188,107 @@ static size_t lpc2_flash_readDirect(struct KBlock *blk, block_idx_t idx, void *b
 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);
+       ASSERT(FLASH_PAGE_SIZE_BYTES == size);
 
        Flash *fls = FLASH_CAST(blk);
+       if (!(fls->blk.priv.flags & KB_WRITE_ONCE))
+               ASSERT(sector_size(idx) <= FLASH_PAGE_SIZE_BYTES);
+
        const uint8_t *buf = (const uint8_t *)_buf;
        cpu_flags_t flags;
 
        //Compute page address of current page.
-       uint32_t addr = sector_addr(idx);
-
-       LOG_INFO("Writing page %ld...\n", idx);
+       uint32_t addr = idx * blk->blk_size;
+       uint32_t sector = addr_to_sector(addr);
+       // Compute the first page index in the sector to manage the status
+       int idx_sector = sector_addr(sector) /  blk->blk_size;
 
+       LOG_INFO("Writing page[%ld]sector[%ld]idx[%d]\n", idx, sector, idx_sector);
        IRQ_SAVE_DISABLE(flags);
 
        IapCmd cmd;
        IapRes res;
        cmd.cmd = PREPARE_SECTOR_FOR_WRITE;
-       cmd.param[0] = cmd.param[1] = idx;
+       cmd.param[0] = cmd.param[1] = sector;
        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] = idx;
-       cmd.param[2] = CPU_FREQ / 1000;
-       iap(&cmd, &res);
        if (res.status != CMD_SUCCESS)
+               goto flash_error;
+
+       if ((fls->blk.priv.flags & KB_WRITE_ONCE) &&
+                       bitarray_blockFull(idx_sector, erase_group[sector], page_dirty, FLASH_PAGE_CNT))
        {
-               LOG_ERR("%ld\n", res.status);
-               fls->hw->status |= FLASH_WR_ERR;
-               return 0;
+               kputs("blocchi pieni\n");
+               ASSERT(0);
+               goto flash_error;
        }
 
-       while (size)
+       bool erase = false;
+       if ((fls->blk.priv.flags & KB_WRITE_ONCE) &&
+                       bitarray_blockEmpty(idx_sector, erase_group[sector], page_dirty, FLASH_PAGE_CNT))
+               erase = true;
+
+       if (!(fls->blk.priv.flags & KB_WRITE_ONCE))
+               erase = true;
+
+       if (erase)
        {
-               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] = idx;
+               cmd.cmd = ERASE_SECTOR;
+               cmd.param[0] = cmd.param[1] = sector;
+               cmd.param[2] = 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;
-               }
 
-               cmd.cmd = COPY_RAM_TO_FLASH;
-               cmd.param[0] = addr;
-               cmd.param[1] = (uint32_t)buf;
-               cmd.param[2] = 4096;
-               cmd.param[3] = CPU_FREQ / 1000;
-               iap(&cmd, &res);
                if (res.status != CMD_SUCCESS)
+                       goto flash_error;
+       }
+
+       LOG_INFO("Writing page [%ld], addr [%ld] in sector[%ld]\n", idx, addr, sector);
+       cmd.cmd = PREPARE_SECTOR_FOR_WRITE;
+       cmd.param[0] = cmd.param[1] = sector;
+       iap(&cmd, &res);
+
+       if (res.status != CMD_SUCCESS)
+               goto flash_error;
+
+       if (fls->blk.priv.flags & KB_WRITE_ONCE)
+       {
+               if (bitarray_check(idx, page_dirty, FLASH_PAGE_CNT))
                {
-                       LOG_ERR("%ld\n", res.status);
-                       fls->hw->status |= FLASH_WR_ERR;
-                       return 0;
+                       ASSERT(0);
+                       goto flash_error;
                }
-
-               size -= 4096;
-               addr += 4096;
-               buf += 4096 / sizeof(uint32_t);
+               else
+                       bitarray_set(idx, page_dirty, FLASH_PAGE_CNT);
        }
 
+       cmd.cmd = COPY_RAM_TO_FLASH;
+       cmd.param[0] = addr;
+       cmd.param[1] = (uint32_t)buf;
+       cmd.param[2] = FLASH_PAGE_SIZE_BYTES;
+       cmd.param[3] = CPU_FREQ / 1000;
+       iap(&cmd, &res);
+
+       if (res.status != CMD_SUCCESS)
+               goto flash_error;
+
        IRQ_RESTORE(flags);
        LOG_INFO("Done\n");
 
        return blk->blk_size;
+
+flash_error:
+       LOG_ERR("%ld\n", res.status);
+       fls->hw->status |= FLASH_WR_ERR;
+       return 0;
 }
 
+static int lpc2_flash_close(UNUSED_ARG(struct KBlock, *blk))
+{
+       memset(page_dirty, 0, sizeof(page_dirty));
+       return 0;
+}
+
+
 static int lpc2_flash_error(struct KBlock *blk)
 {
        Flash *fls = FLASH_CAST(blk);
@@ -269,7 +311,7 @@ static const KBlockVTable flash_lpc2_buffered_vt =
        .load = kblock_swLoad,
        .store = kblock_swStore,
 
-       .close = kblock_swClose,
+       .close = lpc2_flash_close,
 
        .error = lpc2_flash_error,
        .clearerr = lpc2_flash_clearerror,
@@ -280,7 +322,7 @@ static const KBlockVTable flash_lpc2_unbuffered_vt =
        .readDirect = lpc2_flash_readDirect,
        .writeDirect = lpc2_flash_writeDirect,
 
-       .close = kblock_swClose,
+       .close = lpc2_flash_close,
 
        .error = lpc2_flash_error,
        .clearerr = lpc2_flash_clearerror,
@@ -297,25 +339,24 @@ static void common_init(Flash *fls)
        fls->hw = &flash_lpc2_hw;
 
        fls->blk.blk_size = FLASH_PAGE_SIZE_BYTES;
-       fls->blk.blk_cnt = 28;
+       fls->blk.blk_cnt = FLASH_MEM_SIZE / FLASH_PAGE_SIZE_BYTES;
 }
 
-void flash_hw_init(Flash *fls)
+void flash_hw_init(Flash *fls, int flags)
 {
        common_init(fls);
        fls->blk.priv.vt = &flash_lpc2_buffered_vt;
-       fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE;
+       fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE | flags;
        fls->blk.priv.buf = flash_buf;
 
        /* Load the first block in the cache */
        void *flash_start = 0x0;
        memcpy(fls->blk.priv.buf, flash_start, fls->blk.blk_size);
-
-       kprintf("page[%d]\n", sector_addr(22));
 }
 
-void flash_hw_initUnbuffered(Flash *fls)
+void flash_hw_initUnbuffered(Flash *fls, int flags)
 {
        common_init(fls);
        fls->blk.priv.vt = &flash_lpc2_unbuffered_vt;
+       fls->blk.priv.flags |= flags;
 }