X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Farm%2Fdrv%2Fflash_at91.c;h=83cc73b7aaf110505f286a03291336b56bb024a8;hb=b44c11e480505f754d0f7b4ac3067e4ebf5adcc2;hp=778cb11a1997ce42f40891fb27b537bc4d451df1;hpb=507e95236d43b2aa6d6b6e46bde5cb92345ab034;p=bertos.git diff --git a/bertos/cpu/arm/drv/flash_at91.c b/bertos/cpu/arm/drv/flash_at91.c index 778cb11a..83cc73b7 100644 --- a/bertos/cpu/arm/drv/flash_at91.c +++ b/bertos/cpu/arm/drv/flash_at91.c @@ -54,60 +54,63 @@ #include #include -#include +#include #include #include +#include #include -/* - * Check if flash memory is ready to accept other commands. - */ -RAM_FUNC static bool flash_at91_isReady(void) +#define FLASH_START_PAGE DIV_ROUNDUP(FLASH_BOOT_SIZE, FLASH_PAGE_SIZE_BYTES) +#define FLASH_START_ADDR (FLASH_START_PAGE * FLASH_PAGE_SIZE_BYTES) + +/** + * Really send the flash write command. + * + * \note This function has to be placed in RAM because + * executing code from flash while a writing process + * is in progress is forbidden. + */ +RAM_FUNC NOINLINE static void write_page(uint32_t page) { - return (MC_FSR & BV(MC_FRDY)); + // Send the 'write page' command + MC_FCR = MC_KEY | MC_FCMD_WP | (MC_PAGEN_MASK & (page << 8)); + + // Wait for the end of command + while(!(MC_FSR & BV(MC_FRDY))) + { + //NOP; + } } + /** * Send write command. * * After WR command cpu write bufferd page into flash memory. + * */ -RAM_FUNC static void flash_at91_sendWRcmd(uint32_t page) +INLINE void flash_at91_sendWRcmd(uint32_t page) { cpu_flags_t flags; - // Wait for end of command - while(!flash_at91_isReady()) - { - cpu_relax(); - } + LOG_INFO("Writing page %ld...\n", page); IRQ_SAVE_DISABLE(flags); - - // Send the 'write page' command - MC_FCR = MC_KEY | MC_FCMD_WP | (MC_PAGEN_MASK & (page << 8)); - - // Wait for end of command - while(!flash_at91_isReady()) - { - cpu_relax(); - } + write_page(page); IRQ_RESTORE(flags); + LOG_INFO("Done\n"); } /** * Return 0 if no error are occurred after flash memory * read or write operation, otherwise return error code. */ -RAM_FUNC static int flash_at91_getStatus(struct KFile *_fd) +static int flash_at91_getStatus(UNUSED_ARG(struct KFile *, _fd)) { - (void)_fd; - - /* * This bit is set to one if we programming of at least one locked lock * region. @@ -130,37 +133,28 @@ RAM_FUNC static int flash_at91_getStatus(struct KFile *_fd) * Write modified page on internal latch, and then send write command to * flush page to internal flash. */ -RAM_FUNC static void flash_at91_flush(FlashAt91 *fd) +static int flash_at91_flush(KFile *_fd) { + Flash *fd = FLASH_CAST(_fd); if (fd->page_dirty) { //Compute page address of current page. - arm_page_addr_t *addr = (arm_page_addr_t *)((fd->curr_page * FLASH_PAGE_SIZE_BYTES) + FLASH_BASE); + page_addr_t *addr = (page_addr_t *)((fd->curr_page * FLASH_PAGE_SIZE_BYTES) + FLASH_BASE); //Copy modified page into internal latch. - for (arm_page_addr_t page_addr = 0; page_addr < FLASH_PAGE_SIZE_BYTES; page_addr += 4) + for (page_addr_t page_addr = 0; page_addr < FLASH_PAGE_SIZE_BYTES; page_addr += 4) { + // This is needed in order to have a single 32bit write instruction in addr. + // (8 and 16 writes cause unpredictable results). uint32_t data; memcpy(&data, &fd->page_buf[page_addr], sizeof(data)); - *addr = data; - addr++; + *addr++ = data; } // Send write command to transfer page from latch to internal flash memory. flash_at91_sendWRcmd(fd->curr_page); + fd->page_dirty = false; } -} - -/** - * Flush At91 flash function. - * - * Write current buffered page in flash memory (if modified). - * This function erase flash memory page before writing. - */ -static int flash_at91_kfileFlush(struct KFile *_fd) -{ - FlashAt91 *fd = FLASHAT91_CAST(_fd); - flash_at91_flush(fd); return 0; } @@ -169,13 +163,13 @@ static int flash_at91_kfileFlush(struct KFile *_fd) * Check current page and if \a page is different, load it in * temporary buffer. */ -static void flash_at91_loadPage(FlashAt91 *fd, arm_page_t page) +static void flash_at91_loadPage(Flash *fd, page_t page) { if (page != fd->curr_page) { - flash_at91_flush(fd); + flash_at91_flush(&fd->fd); // Load page - memcpy(fd->page_buf, (const char *)((page * FLASH_PAGE_SIZE_BYTES) + FLASH_BASE), FLASH_PAGE_SIZE_BYTES); + memcpy(fd->page_buf, (char *)((page * FLASH_PAGE_SIZE_BYTES) + FLASH_BASE), FLASH_PAGE_SIZE_BYTES); fd->curr_page = page; LOG_INFO("Loaded page %lu\n", fd->curr_page); } @@ -189,20 +183,20 @@ static void flash_at91_loadPage(FlashAt91 *fd, arm_page_t page) */ static size_t flash_at91_write(struct KFile *_fd, const void *_buf, size_t size) { - FlashAt91 *fd = FLASHAT91_CAST(_fd); + Flash *fd = FLASH_CAST(_fd); const uint8_t *buf =(const uint8_t *)_buf; - arm_page_t page; - arm_page_addr_t page_addr; + page_t page; + page_addr_t page_addr; size_t total_write = 0; - size = MIN((kfile_off_t)size, (kfile_off_t)(fd->fd.size - (fd->fd.seek_pos - FLASH_BASE))); + size = MIN((kfile_off_t)size, fd->fd.size - fd->fd.seek_pos); LOG_INFO("Writing at pos[%lu]\n", fd->fd.seek_pos); while (size) { - page = (fd->fd.seek_pos - FLASH_BASE) / FLASH_PAGE_SIZE_BYTES; - page_addr = (fd->fd.seek_pos - FLASH_BASE) % FLASH_PAGE_SIZE_BYTES; + page = (fd->fd.seek_pos + FLASH_START_ADDR) / FLASH_PAGE_SIZE_BYTES; + page_addr = (fd->fd.seek_pos + FLASH_START_ADDR) % FLASH_PAGE_SIZE_BYTES; flash_at91_loadPage(fd, page); @@ -220,84 +214,21 @@ static size_t flash_at91_write(struct KFile *_fd, const void *_buf, size_t size) return total_write; } -/** - * Close file \a fd - */ -static int flash_at91_close(struct KFile *_fd) -{ - FlashAt91 *fd = FLASHAT91_CAST(_fd); - flash_at91_flush(fd); - LOG_INFO("Flash file closed\n"); - - return 0; -} - /** * Open flash file \a fd * \a name and \a mode are unused, cause flash memory is * threated like one file. */ -static void flash_at91_open(struct FlashAt91 *fd) +static void flash_at91_open(struct Flash *fd) { - fd->fd.size = FLASH_BASE + FLASH_MEM_SIZE; - fd->fd.seek_pos = FLASH_BASE + FLASH_BOOT_SIZE; - fd->curr_page = (fd->fd.seek_pos - FLASH_BASE) / FLASH_PAGE_SIZE_BYTES; - - memcpy(fd->page_buf, (const char *)((fd->curr_page * FLASH_PAGE_SIZE_BYTES) + FLASH_BASE), FLASH_PAGE_SIZE_BYTES); + fd->curr_page = FLASH_START_PAGE; + fd->fd.size = FLASH_MEM_SIZE - fd->curr_page * FLASH_PAGE_SIZE_BYTES; + fd->fd.seek_pos = 0; + + memcpy(fd->page_buf, (char *)((fd->curr_page * FLASH_PAGE_SIZE_BYTES) + FLASH_BASE), FLASH_PAGE_SIZE_BYTES); fd->page_dirty = false; - LOG_INFO("Flash file opened\n"); -} - - -/** - * Move \a fd file seek position of \a offset bytes from \a whence. - * - */ -static kfile_off_t flash_at91_seek(struct KFile *_fd, kfile_off_t offset, KSeekMode whence) -{ - FlashAt91 *fd = FLASHAT91_CAST(_fd); - kfile_off_t seek_pos; - - switch (whence) - { - - case KSM_SEEK_SET: - seek_pos = FLASH_BASE + FLASH_BOOT_SIZE; - break; - case KSM_SEEK_END: - seek_pos = fd->fd.size; - break; - case KSM_SEEK_CUR: - seek_pos = fd->fd.seek_pos; - break; - default: - ASSERT(0); - return EOF; - break; - } - - #if LOG_LEVEL >= LOG_LVL_INFO - /* Bound check */ - if (seek_pos + offset > fd->fd.size) - LOG_INFO("seek outside EOF\n"); - #endif - - fd->fd.seek_pos = seek_pos + offset; - - return fd->fd.seek_pos - (FLASH_BASE + FLASH_BOOT_SIZE); -} - -/** - * Reopen file \a fd - */ -static struct KFile *flash_at91_reopen(struct KFile *_fd) -{ - FlashAt91 *fd = FLASHAT91_CAST(_fd); - flash_at91_close(_fd); - flash_at91_open(fd); - - return _fd; + LOG_INFO("Flash file opened, pos %ld, size %ld\n", fd->fd.seek_pos, fd->fd.size); } /** @@ -306,7 +237,7 @@ static struct KFile *flash_at91_reopen(struct KFile *_fd) */ static size_t flash_at91_read(struct KFile *_fd, void *_buf, size_t size) { - FlashAt91 *fd = FLASHAT91_CAST(_fd); + Flash *fd = FLASH_CAST(_fd); uint8_t *buf =(uint8_t *)_buf; size = MIN((kfile_off_t)size, fd->fd.size - fd->fd.seek_pos); @@ -314,10 +245,10 @@ static size_t flash_at91_read(struct KFile *_fd, void *_buf, size_t size) LOG_INFO("Reading at pos[%lu]\n", fd->fd.seek_pos); // Flush current buffered page (if modified). - flash_at91_flush(fd); + flash_at91_flush(&fd->fd); - uint32_t *addr = (uint32_t *)fd->fd.seek_pos; - memcpy(buf, (uint8_t *)addr, size); + kfile_off_t *addr = (kfile_off_t *)(fd->fd.seek_pos + FLASH_START_ADDR); + memcpy(buf, addr, size); fd->fd.seek_pos += size; @@ -330,48 +261,18 @@ static size_t flash_at91_read(struct KFile *_fd, void *_buf, size_t size) * Init module to perform write and read operation on internal * flash memory. */ -void flash_at91_init(FlashAt91 *fd) +void flash_hw_init(struct Flash *fd) { memset(fd, 0, sizeof(*fd)); - DB(fd->fd._type = KFT_FLASHAT91); + // Init base class. + kfile_init(&fd->fd); + DB(fd->fd._type = KFT_FLASH); // Set up flash programming functions. - fd->fd.reopen = flash_at91_reopen; - fd->fd.close = flash_at91_close; fd->fd.write = flash_at91_write; fd->fd.read = flash_at91_read; - fd->fd.seek = flash_at91_seek; fd->fd.error = flash_at91_getStatus; - fd->fd.flush = flash_at91_kfileFlush; + fd->fd.flush = flash_at91_flush; flash_at91_open(fd); - - uint32_t fmcn; - uint32_t fws = 0; - - - /* - * Compute values to insert into mode register. - */ - - /* main clocks in 1.5uS */ - fmcn = (CPU_FREQ/1000000ul) + (CPU_FREQ/2000000ul) + 1; - - /* hard overclocking */ - if (fmcn > 0xFF) - fmcn = 0xFF; - - /* Only allow fmcn=0 if clock period is > 30 us = 33kHz. */ - if (CPU_FREQ <= 33333ul) - fmcn = 0; - - /* Only allow fws=0 if clock frequency is < 30 MHz. */ - if (CPU_FREQ > 30000000ul) - { - fws = 1; - } - - // Set wait states and number of MCK cycles in 1.5 usecs - MC_FMR = fmcn << 16 | fws << 8; - }