4 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
6 This file is part of simavr.
8 simavr is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 simavr is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with simavr. If not, see <http://www.gnu.org/licenses/>.
25 #include "avr_flash.h"
27 static avr_cycle_count_t avr_progen_clear(struct avr_t * avr, avr_cycle_count_t when, void * param)
29 avr_flash_t * p = (avr_flash_t *)param;
30 avr_regbit_clear(p->io.avr, p->selfprgen);
31 printf("avr_progen_clear - SPM not received, clearing PRGEN bit\n");
36 static void avr_flash_write(avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
38 avr_flash_t * p = (avr_flash_t *)param;
40 avr_core_watch_write(avr, addr, v);
42 // printf("** avr_flash_write %02x\n", v);
44 if (avr_regbit_get(avr, p->selfprgen))
45 avr_cycle_timer_register(avr, 4, avr_progen_clear, p); // 4 cycles is very little!
48 static int avr_flash_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param)
50 if (ctl != AVR_IOCTL_FLASH_SPM)
53 avr_flash_t * p = (avr_flash_t *)port;
54 avr_t * avr = p->io.avr;
56 uint16_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8);
58 z |= avr->data[avr->rampz] << 16;
59 uint16_t r01 = avr->data[0] | (avr->data[1] << 8);
61 // printf("AVR_IOCTL_FLASH_SPM %02x Z:%04x R01:%04x\n", avr->data[p->r_spm], z,r01);
62 avr_cycle_timer_cancel(avr, avr_progen_clear, p);
63 avr_regbit_clear(avr, p->selfprgen);
64 if (avr_regbit_get(avr, p->pgers)) {
66 printf("Erasing page %04x (%d)\n", (z / p->spm_pagesize), p->spm_pagesize);
67 for (int i = 0; i < p->spm_pagesize; i++)
68 avr->flash[z++] = 0xff;
69 } else if (avr_regbit_get(avr, p->pgwrt)) {
71 printf("Writing page %04x (%d)\n", (z / p->spm_pagesize), p->spm_pagesize);
72 } else if (avr_regbit_get(avr, p->blbset)) {
73 printf("Setting lock bits (ignored)\n");
76 avr->flash[z++] = r01;
77 avr->flash[z] = r01 >> 8;
82 static avr_io_t _io = {
84 .ioctl = avr_flash_ioctl,
87 void avr_flash_init(avr_t * avr, avr_flash_t * p)
90 // printf("%s init SPM %04x\n", __FUNCTION__, p->r_spm);
92 avr_register_io(avr, &p->io);
93 avr_register_vector(avr, &p->flash);
95 avr_register_io_write(avr, p->r_spm, avr_flash_write, p);