From: asterix Date: Tue, 10 Aug 2010 17:28:06 +0000 (+0000) Subject: Refactor lm3s flash module to new kblock api. X-Git-Tag: 2.6.0~234 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=63986411c74bebcda2a19e61a49ad0b0d933aaf7;p=bertos.git Refactor lm3s flash module to new kblock api. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4156 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/bertos/cpu/cortex-m3/drv/flash_lm3s.c b/bertos/cpu/cortex-m3/drv/flash_lm3s.c index b7498cac..dbabc08a 100644 --- a/bertos/cpu/cortex-m3/drv/flash_lm3s.c +++ b/bertos/cpu/cortex-m3/drv/flash_lm3s.c @@ -40,235 +40,179 @@ #include -#include +#include #include #include + #include /* cpu_relax() */ +#include #include /* 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); -} diff --git a/bertos/cpu/cortex-m3/drv/flash_lm3s.h b/bertos/cpu/cortex-m3/drv/flash_lm3s.h index e70a7919..8c8852fd 100644 --- a/bertos/cpu/cortex-m3/drv/flash_lm3s.h +++ b/bertos/cpu/cortex-m3/drv/flash_lm3s.h @@ -38,23 +38,4 @@ #ifndef FLASH_LM3S_H #define FLASH_LM3S_H -#include -#include - -/* 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 */