2 * Copyright © 2008 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 /* From SWRA124 section 3.1.6 */
23 static uint8_t flash_page[] = {
25 MOV_direct_data, P1DIR, 0x02,
26 MOV_direct_data, P1, 0xFF,
28 MOV_direct_data, FADDRH, 0,
29 #define FLASH_ADDR_HIGH 8
31 MOV_direct_data, FADDRL, 0,
32 #define FLASH_ADDR_LOW 11
34 MOV_DPTR_data16, 0, 0,
35 #define RAM_ADDR_HIGH 13
36 #define RAM_ADDR_LOW 14
39 #define FLASH_WORDS_HIGH 16
42 #define FLASH_WORDS_LOW 18
44 MOV_direct_data, FWT, 0x20,
45 #define FLASH_TIMING 21
47 MOV_direct_data, FCTL, FCTL_ERASE,
50 JB, ACC(FCTL_BUSY_BIT), 0xfb,
52 MOV_direct_data, P1, 0xfd,
54 MOV_direct_data, FCTL, FCTL_WRITE,
61 DJNZ_Rn_rel(5), 0xfa, /* writeWordLoop */
64 JB, ACC(FCTL_SWBSY_BIT), 0xfb, /* writeWaitLoop */
65 DJNZ_Rn_rel(6), 0xf1, /* writeLoop */
66 DJNZ_Rn_rel(7), 0xef, /* writeLoop */
68 MOV_direct_data, P1DIR, 0x00,
69 MOV_direct_data, P1, 0xFF,
73 #define FLASH_RAM 0xf000
76 static uint8_t flash_erase_page[] = {
77 3, MOV_direct_data, FADDRH, 0,
78 #define ERASE_PAGE_HIGH 3
80 3, MOV_direct_data, FADDRL, 0,
81 #define ERASE_PAGE_LOW 7
83 3, MOV_direct_data, FWT, 0x2A,
84 3, MOV_direct_data, FCTL, FCTL_ERASE,
88 static uint8_t flash_read_control[] = {
89 2, MOV_A_direct, FCTL,
95 static uint8_t flash_control_clear[] = {
96 3, MOV_direct_data, FCTL, 0,
97 2, MOV_A_direct, FCTL,
104 ccdbg_flash_erase_page(struct ccdbg *dbg, uint16_t addr)
106 uint16_t page_addr = addr >> 1;
108 uint8_t old[0x10], new[0x10];
111 ccdbg_read_memory(dbg, addr, old, 0x10);
112 flash_erase_page[ERASE_PAGE_HIGH] = page_addr >> 8;
113 flash_erase_page[ERASE_PAGE_LOW] = page_addr & 0xff;
114 status = ccdbg_execute(dbg, flash_erase_page);
115 ccdbg_debug(CC_DEBUG_FLASH, "erase status 0x%02x\n", status);
117 status = ccdbg_execute(dbg, flash_read_control);
118 ccdbg_debug(CC_DEBUG_FLASH, "fctl 0x%02x\n", status);
119 } while (status & FCTL_BUSY);
120 ccdbg_read_memory(dbg, addr, new, 0x10);
121 for (i = 0; i < 0x10; i++)
122 ccdbg_debug(CC_DEBUG_FLASH, "0x%02x -> 0x%02x\n", old[i], new[i]);
123 status = ccdbg_execute(dbg, flash_control_clear);
124 ccdbg_debug(CC_DEBUG_FLASH, "clear fctl 0x%02x\n", status);
130 static uint8_t flash_write[] = {
131 MOV_direct_data, P1DIR, 0x02,
132 MOV_direct_data, P1, 0xFD,
135 JB, ACC(FCTL_BUSY_BIT), 0xf1,
137 MOV_direct_data, FCTL, 0x20,
139 MOV_direct_data, FADDRH, 0,
140 #define WRITE_PAGE_HIGH 16
142 MOV_direct_data, FADDRL, 0,
143 #define WRITE_PAGE_LOW 19
145 MOV_direct_data, FCTL, FCTL_WRITE,
146 MOV_direct_data, FWDATA, 0,
147 #define WRITE_BYTE_0 25
148 MOV_direct_data, FWDATA, 0,
149 #define WRITE_BYTE_1 28
151 JB, ACC(FCTL_SWBSY_BIT), 0xf1,
153 MOV_direct_data, P1, 0xFF,
159 ccdbg_clock_init(struct ccdbg *dbg)
161 static uint8_t set_clkcon_fast[] = {
162 3, MOV_direct_data, CLKCON, 0x00,
166 static uint8_t get_sleep[] = {
167 2, MOV_A_direct, SLEEP,
173 ccdbg_execute(dbg, set_clkcon_fast);
175 status = ccdbg_execute(dbg, get_sleep);
176 } while (!(status & 0x40));
182 ccdbg_flash_write_word(struct ccdbg *dbg, uint16_t addr, uint8_t data[2])
184 uint16_t page_addr = addr >> 1;
189 flash_write[WRITE_PAGE_HIGH] = page_addr >> 8;
190 flash_write[WRITE_PAGE_LOW] = page_addr & 0xff;
191 flash_write[WRITE_BYTE_0] = data[0];
192 flash_write[WRITE_BYTE_1] = data[1];
193 ccdbg_debug(CC_DEBUG_FLASH, "upload flash write\n");
194 ccdbg_write_memory(dbg, 0xf000, flash_write, sizeof(flash_write));
195 ccdbg_set_pc(dbg, 0xf000);
198 status = ccdbg_read_status(dbg);
199 ccdbg_debug(CC_DEBUG_FLASH, "waiting for write 0x%02x\n", status);
200 if ((status & CC_STATUS_CPU_HALTED) != 0)
204 status = ccdbg_execute(dbg, flash_control_clear);
205 ccdbg_debug(CC_DEBUG_FLASH, "clear fctl 0x%02x\n", status);
206 ccdbg_read_memory(dbg, addr, check, 2);
207 for (i = 0; i < 2; i++)
208 ccdbg_debug(CC_DEBUG_FLASH, "0x%02x : 0x%02x\n", data[i], check[i]);
213 #define TIMERS_OFF 0x08
214 #define DMA_PAUSE 0x04
215 #define TIMER_SUSPEND 0x02
216 #define SEL_FLASH_INFO_PAGE 0x01
220 ccdbg_flash_lock(struct ccdbg *dbg, uint8_t lock)
224 uint8_t old[1], new[1];
226 config = ccdbg_rd_config(dbg);
227 ccdbg_wr_config(dbg, config|SEL_FLASH_INFO_PAGE);
230 ccdbg_flash_erase_page(dbg, 0);
231 ccdbg_read_memory(dbg, 0, old, 1);
232 ccdbg_flash_write_word(dbg, 0, bytes);
233 ccdbg_read_memory(dbg, 0, new, 1);
234 ccdbg_debug(CC_DEBUG_FLASH, "flash lock 0x%02x -> 0x%02x\n", old[0], new[0]);
235 ccdbg_wr_config(dbg, config & ~SEL_FLASH_INFO_PAGE);
241 ccdbg_flash_hex_image(struct ccdbg *dbg, struct ao_hex_image *image)
247 uint16_t flash_word_addr;
248 uint16_t flash_words;
249 uint8_t flash_words_high, flash_words_low;
252 uint16_t remain, this_time, start;
253 uint8_t verify[0x400];
256 ccdbg_clock_init(dbg);
257 if (image->address + image->length > 0x8000) {
258 fprintf(stderr, "cannot flash image from 0x%04x to 0x%04x\n",
259 image->address, image->address + image->length);
262 if (image->address & 0x3ff) {
263 fprintf(stderr, "flash image must start on page boundary\n");
273 flash_page[FLASH_TIMING] = fwt;
274 ccdbg_debug(CC_DEBUG_FLASH, "Upload %d flash program bytes to 0x%04x\n",
275 sizeof (flash_page), flash_prog);
276 ccdbg_write_memory(dbg, flash_prog, flash_page, sizeof(flash_page));
278 remain = image->length;
282 if (this_time > 0x400)
285 ccdbg_debug(CC_DEBUG_FLASH, "Upload %d bytes at 0x%04x\n", this_time, ram_addr);
286 ccdbg_write_memory(dbg, ram_addr, image->data + start, this_time);
288 ccdbg_debug(CC_DEBUG_FLASH, "Verify %d bytes in ram\n", this_time);
289 ccdbg_read_memory(dbg, ram_addr, verify, this_time);
290 if (memcmp (image->data + start, verify, this_time) != 0) {
291 fprintf(stderr, "ram verify failed\n");
296 flash_addr = image->address + start;
297 flash_word_addr = flash_addr >> 1;
298 flash_len = this_time + (this_time & 1);
299 flash_words = flash_len >> 1;
301 flash_words_low = flash_words & 0xff;
302 flash_words_high = flash_words >> 8;
304 /* The flash code above is lame */
308 ccdbg_write_uint8(dbg, flash_prog + FLASH_ADDR_HIGH, flash_word_addr >> 8);
309 ccdbg_write_uint8(dbg, flash_prog + FLASH_ADDR_LOW, flash_word_addr & 0xff);
311 ccdbg_write_uint8(dbg, flash_prog + RAM_ADDR_HIGH, ram_addr >> 8);
312 ccdbg_write_uint8(dbg, flash_prog + RAM_ADDR_LOW, ram_addr & 0xff);
314 ccdbg_write_uint8(dbg, flash_prog + FLASH_WORDS_HIGH, flash_words_high);
315 ccdbg_write_uint8(dbg, flash_prog + FLASH_WORDS_LOW, flash_words_low);
317 ccdbg_set_pc(dbg, flash_prog);
318 ccdbg_debug(CC_DEBUG_FLASH, "Flashing %d bytes at 0x%04x\n",
319 this_time, flash_addr);
320 status = ccdbg_resume(dbg);
321 for (times = 0; times < 10; times++) {
322 status = ccdbg_read_status(dbg);
323 ccdbg_debug(CC_DEBUG_FLASH, ".");
324 ccdbg_flush(CC_DEBUG_FLASH);
325 if ((status & CC_STATUS_CPU_HALTED) != 0)
329 ccdbg_debug(CC_DEBUG_FLASH, "\n");
331 fprintf(stderr, "flash page timed out\n");
335 ccdbg_debug(CC_DEBUG_FLASH, "Verify %d bytes in flash\n", this_time);
336 ccdbg_read_memory(dbg, flash_addr, verify, this_time);
337 if (memcmp (image->data + start, verify, this_time) != 0) {
339 fprintf(stderr, "flash verify failed\n");
340 for (i = 0; i < this_time; i++) {
341 if (image->data[start + i] != verify[i])
342 fprintf(stderr, "0x%04x: 0x%02x != 0x%02x\n",
343 start + i, image->data[start+i], verify[i]);