From 8e3f02b0501d4bdedf157a53c12719b2c50e3b9f Mon Sep 17 00:00:00 2001 From: asterix Date: Fri, 13 Aug 2010 13:09:58 +0000 Subject: [PATCH] First refactor to kblock. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4185 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cpu/arm/drv/flash_lpc2.c | 263 ++++++++++++-------------------- bertos/cpu/arm/drv/flash_lpc2.h | 4 +- 2 files changed, 98 insertions(+), 169 deletions(-) diff --git a/bertos/cpu/arm/drv/flash_lpc2.c b/bertos/cpu/arm/drv/flash_lpc2.c index f3c60f1f..ca984332 100644 --- a/bertos/cpu/arm/drv/flash_lpc2.c +++ b/bertos/cpu/arm/drv/flash_lpc2.c @@ -48,9 +48,9 @@ #include #include #include +#include -#include - +#include #include #include @@ -58,23 +58,12 @@ #include +#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; } diff --git a/bertos/cpu/arm/drv/flash_lpc2.h b/bertos/cpu/arm/drv/flash_lpc2.h index 92c7df1c..34eab97c 100644 --- a/bertos/cpu/arm/drv/flash_lpc2.h +++ b/bertos/cpu/arm/drv/flash_lpc2.h @@ -26,13 +26,13 @@ * 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 * - * \brief At91sam7 Internal flash read/write driver. + * \brief NPX lpc23xx embedded flash read/write driver. * * */ -- 2.25.1