From 29139f176f00b23f2856b98c1d1b44d39c0fb8ad Mon Sep 17 00:00:00 2001 From: asterix Date: Wed, 11 Aug 2010 13:00:22 +0000 Subject: [PATCH] Refactor the module to new kblock device. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4162 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cpu/avr/drv/flash_avr.c | 264 ++++++++++----------------------- bertos/cpu/avr/drv/flash_avr.h | 72 +-------- 2 files changed, 85 insertions(+), 251 deletions(-) diff --git a/bertos/cpu/avr/drv/flash_avr.c b/bertos/cpu/avr/drv/flash_avr.c index af1d6de8..8e721036 100644 --- a/bertos/cpu/avr/drv/flash_avr.c +++ b/bertos/cpu/avr/drv/flash_avr.c @@ -35,29 +35,31 @@ * \author Francesco Sacchi * \author Daniele Basile * - * This module implements a kfile-like access for Atmel avr - * internal flash. + * This module implements a kfile-like access for Atmel avr internal flash. * Internal flash writing access is controlled by BOOTSZ fuses, check * datasheet for details. */ #include "flash_avr.h" -#include "cfg/cfg_flash_avr.h" +#include "cfg/cfg_emb_flash.h" + #include // MIN() #include #include #include // Define log settings for cfg/log.h -#define LOG_LEVEL CONFIG_FLASH_AVR_LOG_LEVEL -#define LOG_FORMAT CONFIG_FLASH_AVR_LOG_FORMAT +#define LOG_LEVEL CONFIG_FLASH_EMB_LOG_LEVEL +#define LOG_FORMAT CONFIG_FLASH_EMB_LOG_FORMAT #include #include #include #include +#include +#include #include #include @@ -65,225 +67,115 @@ #include +struct FlashHardware; -/** - * Definition of type for avr flash module. - */ -typedef uint16_t page_addr_t; - - -/** - * Private avr flush funtion. - * - * Write current buffered page in flash memory (if modified). - * This function erase flash memory page before writing. - * - * This function is only use internally in this module. - */ -static void flash_avr_flush(Flash *fd) +static size_t avr_flash_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size) { - if (fd->page_dirty) - { + ASSERT(offset == 0); + ASSERT(size == blk->blk_size); - LOG_INFO("Flushing page %d\n", fd->curr_page); + memcpy_P(buf, (const void *)(uint16_t)(idx * blk->blk_size), size); + return blk->blk_size; +} - // Wait while the SPM instruction is busy. - boot_spm_busy_wait(); +static size_t avr_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); - LOG_INFO("Filling temparary page buffer..."); + uint32_t page_addr = idx * blk->blk_size; + uint32_t addr = idx * blk->blk_size; + const uint8_t *buf = (const uint8_t *)_buf; - // Fill the temporary buffer of the AVR - for (page_addr_t page_addr = 0; page_addr < SPM_PAGESIZE; page_addr += 2) - { - uint16_t word = ((uint16_t)fd->page_buf[page_addr + 1] << 8) | fd->page_buf[page_addr]; + /* Wait while the SPM instruction is busy. */ + boot_spm_busy_wait(); - ATOMIC(boot_page_fill(page_addr, word)); - } - LOG_INFO("Done.\n"); + /* Fill the temporary buffer of the AVR */ + while (size) + { + uint16_t data = ((*buf + 1) << 8) | *buf; + ATOMIC(boot_page_fill(addr, data)); - wdt_reset(); + buf += 2; + size -= 2; + addr += 2; + } - LOG_INFO("Erasing page, addr %u...", fd->curr_page * SPM_PAGESIZE); + wdt_reset(); - /* Page erase */ - ATOMIC(boot_page_erase(fd->curr_page * SPM_PAGESIZE)); + /* Page erase */ + ATOMIC(boot_page_erase(page_addr)); - /* Wait until the memory is erased. */ - boot_spm_busy_wait(); + /* Wait until the memory is erased. */ + boot_spm_busy_wait(); - LOG_INFO("Done.\n"); - LOG_INFO("Writing page, addr %u...", fd->curr_page * SPM_PAGESIZE); + /* Store buffer in flash page. */ + ATOMIC(boot_page_write(page_addr)); - /* Store buffer in flash page. */ - ATOMIC(boot_page_write(fd->curr_page * SPM_PAGESIZE)); - boot_spm_busy_wait(); // Wait while the SPM instruction is busy. + /* Wait while the SPM instruction is busy. */ + boot_spm_busy_wait(); - /* - * Reenable RWW-section again. We need this if we want to jump back - * to the application after bootloading. - */ - ATOMIC(boot_rww_enable()); + /* + * Reenable RWW-section again. We need this if we want to jump back + * to the application after bootloading. + */ + ATOMIC(boot_rww_enable()); - fd->page_dirty = false; - LOG_INFO("Done.\n"); - } + return blk->blk_size; } - -/** - * Flush avr flash function. - * - * Write current buffered page in flash memory (if modified). - * This function erase flash memory page before writing. - */ -static int flash_avr_kfileFlush(struct KFile *_fd) +static int avr_flash_dummy(UNUSED_ARG(struct KBlock, *blk)) { - Flash *fd = FLASH_CAST(_fd); - flash_avr_flush(fd); return 0; } - -/** - * Check current page and if \a page is different, load it in - * temporary buffer. - */ -static void flash_avr_loadPage(Flash *fd, page_t page) +static const KBlockVTable flash_avr_buffered_vt = { - if (page != fd->curr_page) - { - flash_avr_flush(fd); - // Load page - memcpy_P(fd->page_buf, (const char *)(page * SPM_PAGESIZE), SPM_PAGESIZE); - fd->curr_page = page; - LOG_INFO("Loaded page %d\n", fd->curr_page); - } -} + .readDirect = avr_flash_readDirect, + .writeDirect = avr_flash_writeDirect, -/** - * Write program memory. - * Write \a size bytes from buffer \a _buf to file \a fd - * \note Write operations are buffered. - */ -static size_t flash_avr_write(struct KFile *_fd, const void *_buf, size_t size) -{ - Flash *fd = FLASH_CAST(_fd); - const uint8_t *buf =(const uint8_t *)_buf; - - page_t page; - page_addr_t page_addr; - size_t total_write = 0; - - - ASSERT(fd->fd.seek_pos + (kfile_off_t)size <= (kfile_off_t)fd->fd.size); - size = MIN((kfile_off_t)size, fd->fd.size - fd->fd.seek_pos); - - LOG_INFO("Writing at pos[%u]\n", fd->fd.seek_pos); - while (size) - { - page = fd->fd.seek_pos / SPM_PAGESIZE; - page_addr = fd->fd.seek_pos % SPM_PAGESIZE; + .readBuf = kblock_swReadBuf, + .writeBuf = kblock_swWriteBuf, + .load = kblock_swLoad, + .store = kblock_swStore, - flash_avr_loadPage(fd, page); + .error = avr_flash_dummy, + .clearerr = (kblock_clearerr_t)avr_flash_dummy, +}; - size_t wr_len = MIN(size, SPM_PAGESIZE - page_addr); - memcpy(fd->page_buf + page_addr, buf, wr_len); - fd->page_dirty = true; - - buf += wr_len; - fd->fd.seek_pos += wr_len; - size -= wr_len; - total_write += wr_len; - } - LOG_INFO("written %u bytes\n", total_write); - return total_write; -} - -/** - * Open flash file \a fd - * \a name and \a mode are unused, cause flash memory is - * threated like one file. - */ -static void flash_avr_open(struct Flash *fd) +static const KBlockVTable flash_avr_unbuffered_vt = { - fd->curr_page = 0; - memcpy_P(fd->page_buf, (const char *)(fd->curr_page * SPM_PAGESIZE), SPM_PAGESIZE); + .readDirect = avr_flash_readDirect, + .writeDirect = avr_flash_writeDirect, - fd->fd.seek_pos = 0; - fd->fd.size = (uint16_t)(FLASHEND - CONFIG_FLASH_AVR_BOOTSIZE + 1); - fd->page_dirty = false; + .error = avr_flash_dummy, + .clearerr = (kblock_clearerr_t)avr_flash_dummy, +}; - LOG_INFO("Flash file opened\n"); -} +static uint8_t flash_buf[SPM_PAGESIZE]; -/** - * Close file \a fd - */ -static int flash_avr_close(struct KFile *_fd) +static void common_init(Flash *fls) { - Flash *fd = FLASH_CAST(_fd); - flash_avr_flush(fd); - LOG_INFO("Flash file closed\n"); - return 0; -} + memset(fls, 0, sizeof(*fls)); + DB(fls->blk.priv.type = KBT_FLASH); -/** - * Reopen file \a fd - */ -static struct KFile *flash_avr_reopen(struct KFile *fd) -{ - Flash *_fd = FLASH_CAST(fd); - flash_avr_close(fd); - flash_avr_open((struct Flash *)_fd); - return fd; + fls->blk.blk_size = SPM_PAGESIZE; + fls->blk.blk_cnt = (FLASHEND + 1) / SPM_PAGESIZE; } -/** - * 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_avr_read(struct KFile *_fd, void *buf, size_t size) +void flash_hw_init(Flash *fls) { - Flash *fd = FLASH_CAST(_fd); - ASSERT(fd->fd.seek_pos + (kfile_off_t)size <= (kfile_off_t)fd->fd.size); - size = MIN((kfile_off_t)size, fd->fd.size - fd->fd.seek_pos); - - LOG_INFO("Reading at pos[%u]\n", fd->fd.seek_pos); - // Flush current buffered page (if modified). - flash_avr_flush(fd); - - /* - * AVR pointers are 16 bits wide, this hack is needed to avoid - * compiler warning, cause fd->seek_pos is a 32bit offset. - */ - const uint8_t *pgm_addr = (const uint8_t *)0; - pgm_addr += fd->fd.seek_pos; - - memcpy_P(buf, pgm_addr, size); - fd->fd.seek_pos += size; - LOG_INFO("Read %u bytes\n", size); - return size; + common_init(fls); + fls->blk.priv.vt = &flash_avr_buffered_vt; + fls->blk.priv.flags |= KB_BUFFERED | KB_PARTIAL_WRITE; + fls->blk.priv.buf = flash_buf; } -/** - * Init AVR flash read/write file. - */ -void flash_hw_init(struct Flash *fd) +void flash_hw_initUnbuffered(Flash *fls) { - memset(fd, 0, sizeof(*fd)); - DB(fd->fd._type = KFT_FLASH); - - // Set up flash programming functions. - fd->fd.reopen = flash_avr_reopen; - fd->fd.close = flash_avr_close; - fd->fd.read = flash_avr_read; - fd->fd.write = flash_avr_write; - fd->fd.seek = kfile_genericSeek; - fd->fd.flush = flash_avr_kfileFlush; - fd->curr_page = 0; - - flash_avr_open(fd); + common_init(fls); + fls->blk.priv.vt = &flash_avr_unbuffered_vt; } diff --git a/bertos/cpu/avr/drv/flash_avr.h b/bertos/cpu/avr/drv/flash_avr.h index ecbe1b77..6556e95d 100644 --- a/bertos/cpu/avr/drv/flash_avr.h +++ b/bertos/cpu/avr/drv/flash_avr.h @@ -34,74 +34,16 @@ * \author Daniele Basile * * \brief AVR Internal flash read/write driver. - * - * */ -#ifndef FLASH_AT91_H -#define FLASH_AT91_H - -#include - -#include - -#include - -#include - - -#define FLASH_PAGE_SIZE SPM_PAGESIZE - -/** - * Definition of type for avr flash module. - */ -typedef uint16_t page_t; +#ifndef FLASH_AVR_H +#define FLASH_AVR_H -/* Forward declaration */ -struct Flash; +#include "cfg/cfg_emb_flash.h" -/** - * FlashAvr KFile context structure. - * DEPREACTED STRUCTURE! - * Use Flash instead - * - * \{ - */ -typedef struct FlashAvr -{ - /** - * File descriptor. - */ - KFile fd; - - /** - * Flag for checking if current page is modified. - */ - bool page_dirty; - - /** - * Current buffered page. - */ - page_t curr_page; - - /** - * Temporary buffer cointaing data block to - * write on flash. - */ - uint8_t page_buf[SPM_PAGESIZE]; -} FlashAvr; -/* \} */ - -void flash_hw_init(struct Flash *fd); - -/** - * WARNING! - * This function is DEPRECADED! - * use the flash module instead. - */ -INLINE void flash_avr_init(struct FlashAvr *fd) -{ - flash_hw_init((struct Flash *)fd); -} +#if !CONFIG_FLASH_DISABLE_OLD_API + /* For backwards compatibility */ + #define FlashAvr Flash +#endif /* !CONFIG_FLASH_DISABLE_OLD_API */ #endif /* DRV_FLASH_AVR_H */ -- 2.25.1