4 IO module that simulates the AVR EEProm
6 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
8 This file is part of simavr.
10 simavr is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
15 simavr is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with simavr. If not, see <http://www.gnu.org/licenses/>.
27 #include "avr_eeprom.h"
29 static avr_cycle_count_t avr_eempe_clear(struct avr_t * avr, avr_cycle_count_t when, void * param)
31 avr_eeprom_t * p = (avr_eeprom_t *)param;
32 avr_regbit_clear(p->io.avr, p->eempe);
36 static avr_cycle_count_t avr_eei_raise(struct avr_t * avr, avr_cycle_count_t when, void * param)
38 avr_eeprom_t * p = (avr_eeprom_t *)param;
39 avr_raise_interrupt(p->io.avr, &p->ready);
43 static void avr_eeprom_write(avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
45 avr_eeprom_t * p = (avr_eeprom_t *)param;
46 uint8_t eempe = avr_regbit_get(avr, p->eempe);
48 avr_core_watch_write(avr, addr, v);
50 if (!eempe && avr_regbit_get(avr, p->eempe)) {
51 avr_cycle_timer_register(avr, 4, avr_eempe_clear, p);
54 if (eempe && avr_regbit_get(avr, p->eepe)) { // write operation
57 addr = avr->data[p->r_eearl] | (avr->data[p->r_eearh] << 8);
59 addr = avr->data[p->r_eearl];
60 // printf("eeprom write %04x <- %02x\n", addr, avr->data[p->r_eedr]);
61 p->eeprom[addr] = avr->data[p->r_eedr];
62 // Automatically clears that bit (?)
63 avr_regbit_clear(avr, p->eempe);
65 avr_cycle_timer_register_usec(avr, 3400, avr_eei_raise, p); // 3.4ms here
67 if (avr_regbit_get(avr, p->eere)) { // read operation
70 addr = avr->data[p->r_eearl] | (avr->data[p->r_eearh] << 8);
72 addr = avr->data[p->r_eearl];
73 avr->data[p->r_eedr] = p->eeprom[addr];
74 // printf("eeprom read %04x : %02x\n", addr, p->eeprom[addr]);
78 avr_regbit_clear(avr, p->eepe);
79 avr_regbit_clear(avr, p->eere);
82 static int avr_eeprom_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param)
84 avr_eeprom_t * p = (avr_eeprom_t *)port;
88 case AVR_IOCTL_EEPROM_SET: {
89 avr_eeprom_desc_t * desc = (avr_eeprom_desc_t*)io_param;
90 if (!desc || !desc->size || !desc->ee || (desc->offset + desc->size) > p->size) {
91 AVR_LOG(port->avr, LOG_WARNING, "EEPROM: %s: AVR_IOCTL_EEPROM_SET Invalid argument\n",
95 memcpy(p->eeprom + desc->offset, desc->ee, desc->size);
96 AVR_LOG(port->avr, LOG_TRACE, "EEPROM: %s: AVR_IOCTL_EEPROM_SET Loaded %d at offset %d\n",
97 __FUNCTION__, desc->size, desc->offset);
99 case AVR_IOCTL_EEPROM_GET: {
100 avr_eeprom_desc_t * desc = (avr_eeprom_desc_t*)io_param;
101 if (!desc || (desc->offset + desc->size) > p->size) {
102 AVR_LOG(port->avr, LOG_WARNING, "EEPROM: %s: AVR_IOCTL_EEPROM_GET Invalid argument\n",
107 memcpy(desc->ee, p->eeprom + desc->offset, desc->size);
108 else // allow to get access to the read data, for gdb support
109 desc->ee = p->eeprom + desc->offset;
116 static void avr_eeprom_dealloc(struct avr_io_t * port)
118 avr_eeprom_t * p = (avr_eeprom_t *)port;
124 static avr_io_t _io = {
126 .ioctl = avr_eeprom_ioctl,
127 .dealloc = avr_eeprom_dealloc,
130 void avr_eeprom_init(avr_t * avr, avr_eeprom_t * p)
133 // printf("%s init (%d bytes) EEL/H:%02x/%02x EED=%02x EEC=%02x\n",
134 // __FUNCTION__, p->size, p->r_eearl, p->r_eearh, p->r_eedr, p->r_eecr);
136 p->eeprom = malloc(p->size);
137 memset(p->eeprom, 0xff, p->size);
139 avr_register_io(avr, &p->io);
140 avr_register_vector(avr, &p->ready);
142 avr_register_io_write(avr, p->r_eecr, avr_eeprom_write, p);