X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;ds=sidebyside;f=bertos%2Fcpu%2Favr%2Fdrv%2Fflash_avr.c;h=231e01ebb941d77f19e0197b64eaa09d09bc6822;hb=af6f92fdde767ddb88623acead8a59a468c1ae15;hp=c587c5270057387581b7283284628b93c93daf4f;hpb=dd6db266344e7bf6d58673d7ce5b5b3a9ed9e64d;p=bertos.git diff --git a/bertos/cpu/avr/drv/flash_avr.c b/bertos/cpu/avr/drv/flash_avr.c index c587c527..231e01eb 100644 --- a/bertos/cpu/avr/drv/flash_avr.c +++ b/bertos/cpu/avr/drv/flash_avr.c @@ -32,27 +32,34 @@ * * \brief Self programming routines. * - * \version $Id$ * \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_EMB_LOG_LEVEL +#define LOG_FORMAT CONFIG_FLASH_EMB_LOG_FORMAT +#include + #include +#include -#include +#include +#include +#include #include #include @@ -60,242 +67,113 @@ #include +struct FlashHardware; - -/** - * Definition of type for avr flash module. - */ -typedef uint16_t avr_page_addr_t; -typedef uint16_t avr_page_t; - -/** - * Temporary buffer cointaing data block to - * write on flash. - */ -static uint8_t page_buf[SPM_PAGESIZE]; - -/** - * Flag for checking if current page is modified. - */ -bool page_modified; - -/** - * Current buffered page. - */ -static avr_page_t curr_page = 0; - -/* - * 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 internaly in this module. - */ -static void flash_avr_flush(void) +static size_t avr_flash_readDirect(struct KBlock *blk, block_idx_t idx, void *buf, size_t offset, size_t size) { - if (page_modified) - { - kprintf("Flushing page %d\n", 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); - kprintf("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 (avr_page_addr_t page_addr = 0; page_addr < SPM_PAGESIZE; page_addr += 2) - { - uint16_t word = ((uint16_t)page_buf[page_addr + 1] << 8) | page_buf[page_addr]; + /* Wait while the SPM instruction is busy. */ + boot_spm_busy_wait(); - ATOMIC(boot_page_fill(page_addr, word)); - } - kprintf("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; + } - kprintf("Erasing page, addr %u...", curr_page * SPM_PAGESIZE); + wdt_reset(); - /* Page erase */ - ATOMIC(boot_page_erase(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(); - kprintf("Done.\n"); - kprintf("Writing page, addr %u...", curr_page * SPM_PAGESIZE); + /* Store buffer in flash page. */ + ATOMIC(boot_page_write(page_addr)); - /* Store buffer in flash page. */ - ATOMIC(boot_page_write(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()); - page_modified = false; - kprintf("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(UNUSED_ARG(struct KFile *,fd)) +static int avr_flash_dummy(UNUSED_ARG(struct KBlock, *blk)) { - - KFILEFLASHAVR(fd); - flash_avr_flush(); return 0; } - -/** - * Check current page and if \a page is different, load it in - * temporary buffer. - */ -static void flash_avr_loadPage(avr_page_t page) +static const KBlockVTable flash_avr_buffered_vt = { - if (page != curr_page) - { - flash_avr_flush(); - // Load page - memcpy_P(page_buf, (const char *)(page * SPM_PAGESIZE), SPM_PAGESIZE); - curr_page = page; - kprintf("Loaded page %d\n", 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) -{ - KFILEFLASHAVR(fd); - const uint8_t *buf =(const uint8_t *)_buf; - - avr_page_t page; - avr_page_addr_t page_addr; - size_t total_write = 0; + .readBuf = kblock_swReadBuf, + .writeBuf = kblock_swWriteBuf, + .load = kblock_swLoad, + .store = kblock_swStore, + .error = avr_flash_dummy, + .clearerr = (kblock_clearerr_t)avr_flash_dummy, +}; - ASSERT(fd->seek_pos + size <= fd->size); - size = MIN((uint32_t)size, fd->size - fd->seek_pos); - - kprintf("Writing at pos[%u]\n", fd->seek_pos); - while (size) - { - page = fd->seek_pos / SPM_PAGESIZE; - page_addr = fd->seek_pos % SPM_PAGESIZE; - - flash_avr_loadPage(page); - - size_t wr_len = MIN(size, SPM_PAGESIZE - page_addr); - memcpy(page_buf + page_addr, buf, wr_len); - page_modified = true; - - buf += wr_len; - fd->seek_pos += wr_len; - size -= wr_len; - total_write += wr_len; - } - kprintf("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 KFile *fd) +static const KBlockVTable flash_avr_unbuffered_vt = { - KFILEFLASHAVR(fd); - curr_page = 0; - memcpy_P(page_buf, (const char *)(curr_page * SPM_PAGESIZE), SPM_PAGESIZE); + .readDirect = avr_flash_readDirect, + .writeDirect = avr_flash_writeDirect, - fd->seek_pos = 0; - fd->size = (uint16_t)(FLASHEND - CONFIG_FLASH_AVR_BOOTSIZE + 1); - page_modified = false; + .error = avr_flash_dummy, + .clearerr = (kblock_clearerr_t)avr_flash_dummy, +}; - kprintf("Flash file opened\n"); -} +static uint8_t flash_buf[SPM_PAGESIZE]; -/** - * Close file \a fd - */ -static int flash_avr_close(UNUSED_ARG(struct KFile *,fd)) +static void common_init(Flash *fls) { - KFILEFLASHAVR(fd); - flash_avr_flush(); - kprintf("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) -{ - KFILEFLASHAVR(fd); - flash_avr_close(fd); - flash_avr_open(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, int flags) { - KFILEFLASHAVR(fd); - ASSERT(fd->seek_pos + size <= fd->size); - size = MIN((uint32_t)size, fd->size - fd->seek_pos); - - kprintf("Reading at pos[%u]\n", fd->seek_pos); - // Flush current buffered page (if modified). - flash_avr_flush(); - - /* - * 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->seek_pos; - - memcpy_P(buf, pgm_addr, size); - fd->seek_pos += size; - kprintf("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 | flags; + fls->blk.priv.buf = flash_buf; } -/** - * Init AVR flash read/write file. - */ -void flash_avr_init(struct KFile *fd) +void flash_hw_initUnbuffered(Flash *fls, int flags) { - memset(fd, 0, sizeof(*fd)); - DB(fd->_type = KFT_FLASHAVR); - - // Set up flash programming functions. - fd->reopen = flash_avr_reopen; - fd->close = flash_avr_close; - fd->read = flash_avr_read; - fd->write = flash_avr_write; - fd->seek = kfile_genericSeek; - fd->flush = flash_avr_kfileFlush; - - flash_avr_open(fd); + common_init(fls); + fls->blk.priv.vt = &flash_avr_unbuffered_vt; + fls->blk.priv.flags |= flags; }