Refactor lm3s flash module to new kblock api.
authorasterix <asterix@38d2e660-2303-0410-9eaa-f027e97ec537>
Tue, 10 Aug 2010 17:28:06 +0000 (17:28 +0000)
committerasterix <asterix@38d2e660-2303-0410-9eaa-f027e97ec537>
Tue, 10 Aug 2010 17:28:06 +0000 (17:28 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4156 38d2e660-2303-0410-9eaa-f027e97ec537

bertos/cpu/cortex-m3/drv/flash_lm3s.c
bertos/cpu/cortex-m3/drv/flash_lm3s.h

index b7498caceb31e9d34f88d3ea8182f616b1e0bbec..dbabc08ae7185b2979794de9b800fb22dff1eb06 100644 (file)
 
 #include <cfg/macros.h>
 
-#include <io/kfile.h>
+#include <io/kblock.h>
 
 #include <drv/timer.h>
 #include <drv/flash.h>
+
 #include <cpu/power.h> /* cpu_relax() */
+#include <cpu/types.h>
 
 #include <string.h> /* memcpy() */
 
-
-static int flash_lm3s_erase_page(page_t addr)
+struct FlashHardware
 {
-       FLASH_FCMISC_R = FLASH_FCMISC_AMISC;
+       int status;
+};
 
-       FLASH_FMA_R = (volatile uint32_t)addr;
-       FLASH_FMC_R = FLASH_FMC_WRKEY | FLASH_FMC_ERASE;
+static bool flash_wait(struct KBlock *blk)
+{
+       Flash *fls = FLASH_CAST(blk);
+       ticks_t start = timer_clock();
+       while (true)
+       {
+               if (!(FLASH_FMC_R & FLASH_FMC_ERASE))
+                       break;
+
+               if (FLASH_FCRIS_R & FLASH_FCRIS_ARIS)
+               {
+                       fls->hw->status |= FLASH_WR_PROTECT;
+                       LOG_ERR("wr protect..\n");
+                       return false;
+               }
+
+               if (timer_clock() - start > ms_to_ticks(CONFIG_FLASH_WR_TIMEOUT))
+               {
+                       fls->hw->status |= FLASH_WR_TIMEOUT;
+                       LOG_ERR("Timeout..\n");
+                       return false;
+               }
 
-       while (FLASH_FMC_R & FLASH_FMC_ERASE)
                cpu_relax();
-       if (FLASH_FCRIS_R & FLASH_FCRIS_ARIS)
-               return -1;
-       return 0;
+       }
+
+       return true;
 }
 
-static int flash_lm3s_write_word(page_t addr, const uint8_t *data, size_t len)
+static int lm3s_erasePage(struct KBlock *blk, uint32_t addr)
 {
        FLASH_FCMISC_R = FLASH_FCMISC_AMISC;
 
-       uint32_t _data;
-       memcpy(&_data, data, len);
        FLASH_FMA_R = (volatile uint32_t)addr;
-       FLASH_FMD_R = (volatile uint32_t)_data;
-       FLASH_FMC_R = FLASH_FMC_WRKEY | FLASH_FMC_WRITE;
+       FLASH_FMC_R = FLASH_FMC_WRKEY | FLASH_FMC_ERASE;
 
-       while (FLASH_FMC_R & FLASH_FMC_WRITE)
-               cpu_relax();
-       if (FLASH_FCRIS_R & FLASH_FCRIS_ARIS)
-               return -1;
-       return 0;
+       return flash_wait(blk);
 }
 
-static void _flash_lm3s_flush(Flash *fd)
+static int lm3s_writeWord(struct KBlock *blk, uint32_t addr, uint32_t data)
 {
-       if (!fd->page_dirty)
-               return;
+       FLASH_FCMISC_R = FLASH_FCMISC_AMISC;
 
-       LOG_INFO("Erase page %p\n", fd->curr_page);
-       flash_lm3s_erase_page(fd->curr_page);
+       FLASH_FMA_R = (volatile uint32_t)addr;
+       FLASH_FMD_R = (volatile uint32_t)data;
+       FLASH_FMC_R = FLASH_FMC_WRKEY | FLASH_FMC_WRITE;
 
-       LOG_INFO("Flush page %p\n", fd->curr_page);
-       for (int i = 0; i < FLASH_PAGE_SIZE_BYTES; i+=4)
-               flash_lm3s_write_word(fd->curr_page + i, &fd->page_buf[i], sizeof(uint32_t));
-       fd->page_dirty = false;
+       return flash_wait(blk);
 }
 
-static void flash_lm3s_load_page(Flash *fd, page_t page)
+static size_t lm3s_flash_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size)
 {
-       ASSERT(!((size_t)page % FLASH_PAGE_SIZE_BYTES));
-
-       if (page == fd->curr_page)
-               return;
-
-       /* Flush old page */
-       _flash_lm3s_flush(fd);
-
-       /* Load a new page */
-       memcpy(fd->page_buf, FLASH_BASE + (uint8_t *)page, FLASH_PAGE_SIZE_BYTES);
-       fd->curr_page = page;
-       LOG_INFO("Loaded page %p\n", fd->curr_page);
+       memcpy(buf, (void *)(idx * blk->blk_size + offset), size);
+       return size;
 }
 
-/**
- * Write program memory.
- * Write \a size bytes from buffer \a _buf to file \a fd
- * \note Write operations are not buffered.
- */
-static size_t flash_lm3s_write(struct KFile *_fd, const void *_buf, size_t size)
+static size_t lm3s_flash_writeDirect(struct KBlock *blk, block_idx_t idx, const void *_buf, size_t offset, size_t size)
 {
-       Flash *fd = FLASH_CAST(_fd);
-       const uint8_t *buf =(const uint8_t *)_buf;
-       size_t total_write = 0;
-       size_t len;
+       ASSERT(offset == 0);
+       ASSERT(size == blk->blk_size);
 
-       size = MIN((kfile_off_t)size,
-               (kfile_off_t)(fd->fd.size - (fd->fd.seek_pos - FLASH_BASE)));
+       if (!lm3s_erasePage(blk, (idx * blk->blk_size)))
+               return 0;
+
+       uint32_t addr = idx * blk->blk_size;
+       const uint8_t *buf = (const uint8_t *)_buf;
 
-       LOG_INFO("Writing at pos[%lx]\n", fd->fd.seek_pos);
        while (size)
        {
-               page_t page = (fd->fd.seek_pos & ~(FLASH_PAGE_SIZE_BYTES - 1));
-               size_t offset = fd->fd.seek_pos % FLASH_PAGE_SIZE_BYTES;
-
-               flash_lm3s_load_page(fd, page);
-
-               len = MIN(size, FLASH_PAGE_SIZE_BYTES - offset);
+               uint32_t data = (*(buf + 3) << 24) |
+                                               (*(buf + 2) << 16) |
+                                               (*(buf + 1) << 8)  |
+                                               *buf;
 
-               memcpy((uint8_t *)fd->page_buf + offset, buf, len);
-               fd->page_dirty = true;
+               if (!lm3s_writeWord(blk, addr, data))
+                       return 0;
 
-               buf += len;
-               fd->fd.seek_pos += len;
-               size -= len;
-               total_write += len;
+               size -= 4;
+               buf += 4;
+               addr += 4;
        }
-       LOG_INFO("written %u bytes\n", total_write);
-       return total_write;
+
+       return blk->blk_size;
 }
 
-/**
- * Close file \a fd
- */
-static int flash_lm3s_close(struct KFile *_fd)
+static int lm3s_flash_error(struct KBlock *blk)
 {
-       Flash *fd = FLASH_CAST(_fd);
-       _flash_lm3s_flush(fd);
-       LOG_INFO("Flash file closed\n");
-       return 0;
+       Flash *fls = FLASH_CAST(blk);
+       return fls->hw->status;
 }
 
-/**
- * Open flash file \a fd
- */
-static void flash_lm3s_open(Flash *fd)
+static void lm3s_flash_clearerror(struct KBlock *blk)
 {
-       fd->fd.size = FLASH_BASE + FLASH_MEM_SIZE;
-       fd->fd.seek_pos = FLASH_BASE;
-       /*
-        * Set an invalid page to force the load of the next actually used page
-        * in cache.
-        */
-       fd->curr_page = FLASH_BASE + FLASH_MEM_SIZE;
-
-       fd->page_dirty = false;
-       LOG_INFO("Flash file opened\n");
+       Flash *fls = FLASH_CAST(blk);
+       fls->hw->status = 0;
 }
 
-/**
- * Move \a fd file seek position of \a offset bytes from \a whence.
- */
-static kfile_off_t flash_lm3s_seek(struct KFile *_fd, kfile_off_t offset, KSeekMode whence)
+static const KBlockVTable flash_lm3s_buffered_vt =
 {
-       Flash *fd = FLASH_CAST(_fd);
-       kfile_off_t seek_pos;
+       .readDirect = lm3s_flash_readDirect,
+       .writeDirect = lm3s_flash_writeDirect,
 
-       switch (whence)
-       {
-       case KSM_SEEK_SET:
-               seek_pos = FLASH_BASE;
-               break;
-       case KSM_SEEK_END:
-               seek_pos = FLASH_BASE + fd->fd.size;
-               break;
-       case KSM_SEEK_CUR:
-               seek_pos = fd->fd.seek_pos;
-               break;
-       default:
-               ASSERT(0);
-               return EOF;
-               break;
-       }
-       if (seek_pos + offset > fd->fd.size)
-               LOG_ERR("seek outside EOF\n");
-       fd->fd.seek_pos = seek_pos + offset;
+       .readBuf = kblock_swReadBuf,
+       .writeBuf = kblock_swWriteBuf,
+       .load = kblock_swLoad,
+       .store = kblock_swStore,
 
-       return fd->fd.seek_pos - FLASH_BASE;
-}
+       .error = lm3s_flash_error,
+       .clearerr = lm3s_flash_clearerror,
+};
 
-/**
- * Reopen file \a fd
- */
-static struct KFile *flash_lm3s_reopen(struct KFile *_fd)
+static const KBlockVTable flash_lm3s_unbuffered_vt =
 {
-       Flash *fd = FLASH_CAST(_fd);
-       flash_lm3s_close(_fd);
-       flash_lm3s_open(fd);
+       .readDirect = lm3s_flash_readDirect,
+       .writeDirect = lm3s_flash_writeDirect,
 
-       return _fd;
-}
+       .error = lm3s_flash_error,
+       .clearerr = lm3s_flash_clearerror,
+};
 
-/**
- * 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_lm3s_read(struct KFile *_fd, void *_buf, size_t size)
+/* Flash memory mapping */
+#if CPU_CM3_LM3S1968
+       #define EMB_FLASH_SIZE               0x40000 //< 256KiB
+       #define EMB_FLASH_PAGE_SIZE          0x400   //< 1KiB
+#else
+       #error Unknown CPU
+#endif
+
+static struct FlashHardware flash_lm3s_hw;
+static uint8_t flash_buf[EMB_FLASH_PAGE_SIZE];
+
+static void common_init(Flash *fls)
 {
-       Flash *fd = FLASH_CAST(_fd);
-       uint8_t *buf =(uint8_t *)_buf, *addr;
-
-       size = MIN((kfile_off_t)size, fd->fd.size - fd->fd.seek_pos);
-
-       LOG_INFO("Reading at pos[%lx]\n", fd->fd.seek_pos);
-       /* Check if we can get current cached page */
-       if ((size_t)fd->fd.seek_pos / FLASH_PAGE_SIZE_BYTES ==
-                               (size_t)fd->curr_page)
-               addr = (uint8_t *)fd->curr_page +
-                       fd->fd.seek_pos % FLASH_PAGE_SIZE_BYTES;
-       else
-               addr = (uint8_t *)fd->fd.seek_pos;
-       memcpy(buf, (uint8_t *)addr, size);
-       fd->fd.seek_pos += size;
-
-       LOG_INFO("Read %u bytes\n", size);
-       return size;
+       memset(fls, 0, sizeof(*fls));
+       DB(fls->blk.priv.type = KBT_FLASH);
+
+       FLASH_USECRL_R = CPU_FREQ / 1000000 - 1;
+
+       fls->hw = &flash_lm3s_hw;
+
+       fls->blk.blk_size = EMB_FLASH_PAGE_SIZE;
+       fls->blk.blk_cnt =  EMB_FLASH_SIZE / EMB_FLASH_PAGE_SIZE;
 }
 
-static int flash_lm3s_flush(struct KFile *_fd)
-{
-       Flash *fd = FLASH_CAST(_fd);
 
-       _flash_lm3s_flush(fd);
-       return 0;
+void flash_hw_init(Flash *fls)
+{
+       common_init(fls);
+       fls->blk.priv.vt = &flash_lm3s_buffered_vt;
+       fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE;
+       fls->blk.priv.buf = flash_buf;
 }
 
-/**
- * Init module to perform write and read operation on internal
- * flash memory.
- */
-void flash_hw_init(Flash *fd)
+void flash_hw_initUnbuffered(Flash *fls)
 {
-       memset(fd, 0, sizeof(*fd));
-       DB(fd->fd._type = KFT_FLASH);
+       common_init(fls);
+       fls->blk.priv.vt = &flash_lm3s_unbuffered_vt;
+}
 
-       fd->fd.reopen = flash_lm3s_reopen;
-       fd->fd.close = flash_lm3s_close;
-       fd->fd.write = flash_lm3s_write;
-       fd->fd.read = flash_lm3s_read;
-       fd->fd.seek = flash_lm3s_seek;
-       fd->fd.flush = flash_lm3s_flush;
 
-       FLASH_USECRL_R = CPU_FREQ / 1000000 - 1;
 
-       flash_lm3s_open(fd);
-}
index e70a7919fb3ca0323f680b5541e080f7d70e6675..8c8852fd775a1088a3c9cebaf215bd1cd71974f4 100644 (file)
 #ifndef FLASH_LM3S_H
 #define FLASH_LM3S_H
 
-#include <cpu/types.h>
-#include <io/kfile.h>
-
-/* Flash memory mapping */
-#define FLASH_MEM_SIZE          0x40000 //< 256KiB
-#define FLASH_PAGE_SIZE_BYTES  0x400   //< 1KiB
-
-
-#define FLASH_PAGE_SIZE    FLASH_PAGE_SIZE_BYTES
-
-/**
- * Define data type to manage page and memory address.
- */
-typedef uint32_t page_t;
-
-struct Flash;
-
-void flash_hw_init(struct Flash *fd);
-
 #endif /* FLASH_LM3S_H */