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>
25 typedef uint16_t page_addr_t;
26 typedef uint16_t page_t;
29 * Temporary buffer for cointain data block to
32 static uint8_t page_buf[PAGEBUF];
35 * Store current flash page memory in use.
37 static page_t curr_pag_num = 0;
44 static void prog_erase_flash(void)
48 /* Erase the flash ROM */
51 * SPM uses Z pointer but the pointer is only 16 bit and
52 * can only address up to 64Kbytes FLASH. Higher locations
53 * require the use of RAMPZ
57 for (flash_addr = 0; (flash_addr < (uint16_t)(APP_END & 0xFFFF)) | (RAMPZ == 0x00));
62 write_page(flash_addr, BV(PGERS) + BV(SPMEN));
64 /* Re-enable the RWW section */
65 write_page(flash_addr, BV(REENABLE_RWW_BIT) + BV(SPMEN));
67 /* Last section on lower 64k segment is erased */
68 if(flashgg_addr >= (0xFFFF - PAGESIZE))
70 /* RAMPZ has to be incremented into upper 64k segment */
74 #else /* LARGE_MEMORY */
75 /* Application section = 60 pages */
76 for (flash_addr = 0; flash_addr < APP_END; flash_addr += PAGESIZE)
81 write_page(flash_addr, BV(PGERS) + BV(SPMEN));
82 /* Re-enable RWW section */
83 write_page(flash_addr, BV(REENABLE_RWW_BIT) + BV(SPMEN));
85 #endif /* LARGE_MEMORY */
90 * Write a page in program memory.
92 static void prog_pagewrite(uint16_t addr)
94 write_page(addr, BV(PGWRT) + BV(SPMEN));
96 /* Re-enable the RWW section */
97 write_page(addr, BV(REENABLE_RWW_BIT) + BV(SPMEN));
102 * Delete a page in program memory.
104 static void prog_pagedelete(uint16_t addr)
107 write_page(addr, BV(PGERS) + BV(SPMEN));
109 /* Re-enable the RWW section */
110 write_page(addr, BV(REENABLE_RWW_BIT) + BV(SPMEN));
114 * Flush temporary buffer into flash memory.
116 static void prog_flush(void)
119 /* Fill the temporary buffer of the AVR */
120 for (page_addr_t page_addr = 0; page_addr < PAGEBUF; page_addr += 2)
121 fill_temp_buffer(page_buf[page_addr + 1] | (uint16_t)page_buf[page_addr] << 8, page_addr);
127 prog_pagedelete(curr_page_num * PAGEBUF);
130 prog_pagewrite(curr_page_num * PAGEBUF);
134 * Write program memory.
135 * This function to write on flash memory load a selected page from
136 * flash memory and save it in temporary buffer. Them update temporary buffer
137 * with \param buf data. We write in flash memory everery time we
138 * change current page memory.
141 size_t prog_write(struct _KFile *fd, const char *buf, size_t size)
145 page_addr_t page_addr;
146 size_t total_write = 0;
151 /* Current page memory */
152 page = fd->SeekPos / PAGEBUF;
154 /* Address in page memory */
155 page_addr = fd->SeekPos % PAGEBUF;
159 wr_len = MIN(size, PAGEBUF - page_addr);
160 memcpy(page_buf + page_addr, buf, wr_len);
163 fd->SeekPos += wr_len;
165 total_write += wr_len;
167 /* Return total byte write on flash memory */
174 * Load select \param page memory buffer from AVR flash memory.
175 * If select page is not current page, we flush it, and then we load
176 * select page memory flash.
178 void prog_loadPage(page_t page)
180 if (page != curr_page_num)
183 /* Load selet page in temporary buffer store into RAM */
184 memcpy_P(page_buf, (const char *)(page * PAGEBUF), PAGEBUF);
185 /* Update current page */
186 curr_page_num = page;