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 void avr_eeprom_run(avr_io_t * port)
31 avr_eeprom_t * p = (avr_eeprom_t *)port;
32 avr_t * avr = p->io.avr;
33 //printf("%s\n", __FUNCTION__);
34 if (p->eempe_clear_timer) {
35 p->eempe_clear_timer--;
36 if (p->eempe_clear_timer == 0) {
37 avr_regbit_clear(avr, p->eempe);
40 if (p->ready_raise_timer) {
41 p->ready_raise_timer--;
42 if (p->ready_raise_timer == 0) {
43 avr_raise_interrupt(avr, &p->ready);
48 static void avr_eeprom_write(avr_t * avr, uint8_t addr, uint8_t v, void * param)
50 avr_eeprom_t * p = (avr_eeprom_t *)param;
51 uint8_t eempe = avr_regbit_get(avr, p->eempe);
53 avr_core_watch_write(avr, addr, v);
55 if (!eempe && avr_regbit_get(avr, p->eempe)) {
56 p->eempe_clear_timer = 4; // auto clear, later
59 if (eempe && avr_regbit_get(avr, p->eepe)) { // write operation
60 uint16_t addr = avr->data[p->r_eearl] | (avr->data[p->r_eearh] << 8);
61 // printf("eeprom write %04x <- %02x\n", addr, avr->data[p->r_eedr]);
62 p->eeprom[addr] = avr->data[p->r_eedr];
63 // Automatically clears that bit (?)
64 p->eempe_clear_timer = 0;
65 avr_regbit_clear(avr, p->eempe);
67 p->ready_raise_timer = 1024; // make a avr_milliseconds_to_cycle(...) 3.4ms here
69 if (avr_regbit_get(avr, p->eere)) { // read operation
70 uint16_t addr = avr->data[p->r_eearl] | (avr->data[p->r_eearh] << 8);
71 avr->data[p->r_eedr] = p->eeprom[addr];
72 // printf("eeprom read %04x : %02x\n", addr, p->eeprom[addr]);
76 avr_regbit_clear(avr, p->eepe);
77 avr_regbit_clear(avr, p->eere);
80 static int avr_eeprom_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param)
82 avr_eeprom_t * p = (avr_eeprom_t *)port;
86 case AVR_IOCTL_EEPROM_SET: {
87 avr_eeprom_desc_t * desc = (avr_eeprom_desc_t*)io_param;
88 if (!desc || !desc->size || !desc->ee || (desc->offset + desc->size) >= p->size) {
89 printf("%s: AVR_IOCTL_EEPROM_SET Invalid argument\n",
93 memcpy(p->eeprom + desc->offset, desc->ee, desc->size);
94 printf("%s: AVR_IOCTL_EEPROM_SET Loaded %d at offset %d\n",
95 __FUNCTION__, desc->size, desc->offset);
97 case AVR_IOCTL_EEPROM_GET: {
98 avr_eeprom_desc_t * desc = (avr_eeprom_desc_t*)io_param;
99 if (!desc || (desc->offset + desc->size) >= p->size) {
100 printf("%s: AVR_IOCTL_EEPROM_GET Invalid argument\n",
105 memcpy(desc->ee, p->eeprom + desc->offset, desc->size);
106 else // allow to get access to the read data, for gdb support
107 desc->ee = p->eeprom + desc->offset;
114 static avr_io_t _io = {
116 .run = avr_eeprom_run,
117 .ioctl = avr_eeprom_ioctl,
120 void avr_eeprom_init(avr_t * avr, avr_eeprom_t * p)
123 // printf("%s init (%d bytes) EEL/H:%02x/%02x EED=%02x EEC=%02x\n",
124 // __FUNCTION__, p->size, p->r_eearl, p->r_eearh, p->r_eedr, p->r_eecr);
126 p->eeprom = malloc(p->size);
127 memset(p->eeprom, 0xff, p->size);
129 avr_register_io(avr, &p->io);
130 avr_register_vector(avr, &p->ready);
132 avr_register_io_write(avr, p->r_eecr, avr_eeprom_write, p);