From 594bfc507f2901777e93ca03fa34f4245a752b35 Mon Sep 17 00:00:00 2001 From: asterix Date: Thu, 7 Jun 2007 09:09:57 +0000 Subject: [PATCH] Abb first skel of programmming AVR flash memory. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@791 38d2e660-2303-0410-9eaa-f027e97ec537 --- mware/prog.h | 44 ++++++++++++++++++ mware/prog_avr.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100755 mware/prog.h create mode 100755 mware/prog_avr.c diff --git a/mware/prog.h b/mware/prog.h new file mode 100755 index 00000000..f197975d --- /dev/null +++ b/mware/prog.h @@ -0,0 +1,44 @@ +/** + * \file + * + * + * \brief Generic program read/write routines interface + * + * This module implements an interface function for programming + * a CPU flash memory. To guarantee correct memory writing, we + * use a rotating hash algorithm. + * + * + * \version $Id$ + * \author Francesco Sacchi + * \author Daniele Basile + */ + +#ifndef PROG_H +#define PROG_H + +#include +#include +#include + +/** + * Generic interface of progress status function. + * \param value is current progress value + * \param max is max progress value + * \return True if programming should continue + * \return False to stop programming + */ +typedef bool (*progress_func_t) (int value, int max); + +/** + * Generic interface for programming a CPU flash memory. + * \param *file is the Kfile pointer to write + * \param progress is progress fuction pointer, can be NULL if not used + * \return rotating hash of file written + */ +rotating_t prog_write(struct _KFile *file, progress_func_t progress); + +#endif /* PROG_H */ diff --git a/mware/prog_avr.c b/mware/prog_avr.c new file mode 100755 index 00000000..05c1ab19 --- /dev/null +++ b/mware/prog_avr.c @@ -0,0 +1,118 @@ +/** + * \file + * + * + * \brief Self programming routines + * + * \version $Id$ + * \author Francesco Sacchi + */ + +#include "prog.h" +#include +#include // MIN() +#include +#include +#include +#include +#include + +/** + * Erase Flash. + */ +static void prog_erase_flash(void) +{ + uint32_t flash_addr; + /* Erase the flash ROM */ + #ifdef LARGE_MEMORY + /* + * SPM uses Z pointer but the pointer is only 16 bit and + * can only address up to 64Kbytes FLASH. Higher locations + * require the use of RAMPZ + */ + RAMPZ = 0x00; + + for (flash_addr = 0; (flash_addr < (uint16_t)(APP_END & 0xFFFF)) | (RAMPZ == 0x00); flash_addr += PAGESIZE) + { + wdt_reset(); + + write_page(flash_addr, BV(PGERS) + BV(SPMEN)); /* Page erase */ + write_page(flash_addr, BV(REENABLE_RWW_BIT) + BV(SPMEN)); /* Re-enable the RWW section */ + + if(flashgg_addr >= (0xFFFF - PAGESIZE)) /* Last section on lower 64k segment is erased */ + RAMPZ = BV(RAMPZ0); /* RAMPZ has to be incremented into upper 64k segment */ + } + RAMPZ = 0x00; + #else /* LARGE_MEMORY */ + for (flash_addr = 0; flash_addr < APP_END; flash_addr += PAGESIZE) /* Application section = 60 pages */ + { + wdt_reset(); + + /* Page erase */ + write_page(flash_addr, BV(PGERS) + BV(SPMEN)); + /* Re-enable RWW section */ + write_page(flash_addr, BV(REENABLE_RWW_BIT) + BV(SPMEN)); + } + #endif /* LARGE_MEMORY */ +} + + +/** + * Write a page in program memory. + */ +static void prog_pagewrite(uint16_t addr) +{ + write_page(addr, BV(PGWRT) + BV(SPMEN)); + /* Re-enable the RWW section */ + write_page(addr, BV(REENABLE_RWW_BIT) + BV(SPMEN)); +} + + +/** + * Write program memory. + */ +rotating_t prog_write(struct _KFile *file, progress_func_t progress) +{ + size_t size; + rotating_t rot = 0; + uint32_t flash_addr = 0; + uint16_t page_addr; + uint8_t buf[PAGESIZE]; + + /* We erase fash memory before to write inside */ + prog_erase_flash(); + + for (;;) + { + wdt_reset(); + + /* Read data from file */ + size = file->read(file, buf, PAGESIZE); + + /* If we reached end of file exit */ + if (!size) + break; + + /* Update checksum */ + rotating_update(buf, size, &rot); + + /* Fill the temporary buffer of the AVR */ + for (page_addr = 0; page_addr < size; page_addr += 2) + fill_temp_buffer(buf[page_addr + 1] | (uint16_t)buf[page_addr] << 8, page_addr); + + /* Page write */ + prog_pagewrite(flash_addr); + + /* Update progess (if present) */ + if (progress) + if (!progress(file->SeekPos, file->Size)) + break; + + flash_addr += size; + } + + return rot +} -- 2.25.1