4 * Copyright 2004 Develer S.r.l. (http://www.develer.com/)
8 * \brief Self programming routines
11 * \author Francesco Sacchi <batt@develer.com>
16 #include <cfg/macros.h> // MIN()
17 #include <cfg/compiler.h>
21 #include <algos/rotating_hash.h>
26 static void prog_erase_flash(void)
29 /* Erase the flash ROM */
32 * SPM uses Z pointer but the pointer is only 16 bit and
33 * can only address up to 64Kbytes FLASH. Higher locations
34 * require the use of RAMPZ
38 for (flash_addr = 0; (flash_addr < (uint16_t)(APP_END & 0xFFFF)) | (RAMPZ == 0x00); flash_addr += PAGESIZE)
42 write_page(flash_addr, BV(PGERS) + BV(SPMEN)); /* Page erase */
43 write_page(flash_addr, BV(REENABLE_RWW_BIT) + BV(SPMEN)); /* Re-enable the RWW section */
45 if(flashgg_addr >= (0xFFFF - PAGESIZE)) /* Last section on lower 64k segment is erased */
46 RAMPZ = BV(RAMPZ0); /* RAMPZ has to be incremented into upper 64k segment */
49 #else /* LARGE_MEMORY */
50 for (flash_addr = 0; flash_addr < APP_END; flash_addr += PAGESIZE) /* Application section = 60 pages */
55 write_page(flash_addr, BV(PGERS) + BV(SPMEN));
56 /* Re-enable RWW section */
57 write_page(flash_addr, BV(REENABLE_RWW_BIT) + BV(SPMEN));
59 #endif /* LARGE_MEMORY */
64 * Write a page in program memory.
66 static void prog_pagewrite(uint16_t addr)
68 write_page(addr, BV(PGWRT) + BV(SPMEN));
69 /* Re-enable the RWW section */
70 write_page(addr, BV(REENABLE_RWW_BIT) + BV(SPMEN));
75 * Write program memory.
77 rotating_t prog_write(struct _KFile *file, progress_func_t progress)
81 uint32_t flash_addr = 0;
83 uint8_t buf[PAGESIZE];
85 /* We erase fash memory before to write inside */
92 /* Read data from file */
93 size = file->read(file, buf, PAGESIZE);
95 /* If we reached end of file exit */
100 rotating_update(buf, size, &rot);
102 /* Fill the temporary buffer of the AVR */
103 for (page_addr = 0; page_addr < size; page_addr += 2)
104 fill_temp_buffer(buf[page_addr + 1] | (uint16_t)buf[page_addr] << 8, page_addr);
107 prog_pagewrite(flash_addr);
109 /* Update progess (if present) */
111 if (!progress(file->SeekPos, file->Size))