b00cfc7cf79b870bb927adc0131089d0a5464098
[simavr] / simavr / sim / sim_avr.c
1 /*
2         sim_avr.c
3
4         Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
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.
12
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.
17
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/>.
20  */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include "sim_avr.h"
27 #include "sim_core.h"
28 #include "sim_gdb.h"
29 #include "avr_uart.h"
30 #include "sim_vcd_file.h"
31 #include "avr_mcu_section.h"
32
33
34 int avr_init(avr_t * avr)
35 {
36         avr->flash = malloc(avr->flashend + 1);
37         memset(avr->flash, 0xff, avr->flashend + 1);
38         avr->data = malloc(avr->ramend + 1);
39         memset(avr->data, 0, avr->ramend + 1);
40 #ifdef CONFIG_SIMAVR_TRACE
41         avr->trace_data = calloc(1, sizeof(struct avr_trace_data_t));
42 #endif
43
44         // cpu is in limbo before init is finished.
45         avr->state = cpu_Limbo;
46         avr->frequency = 1000000;       // can be overriden via avr_mcu_section
47         if (avr->special_init)
48                 avr->special_init(avr);
49         if (avr->init)
50                 avr->init(avr);
51         // set default (non gdb) fast callbacks
52         avr->run = avr_callback_run_raw;
53         avr->sleep = avr_callback_sleep_raw;
54         avr->state = cpu_Running;
55         avr_reset(avr); 
56         return 0;
57 }
58
59 void avr_terminate(avr_t * avr)
60 {
61         if (avr->special_deinit)
62                 avr->special_deinit(avr);
63         if (avr->vcd) {
64                 avr_vcd_close(avr->vcd);
65                 avr->vcd = NULL;
66         }
67         avr_deallocate_ios(avr);
68
69         if (avr->flash) free(avr->flash);
70         if (avr->data) free(avr->data);
71         avr->flash = avr->data = NULL;
72 }
73
74 void avr_reset(avr_t * avr)
75 {
76         memset(avr->data, 0x0, avr->ramend + 1);
77         _avr_sp_set(avr, avr->ramend);
78         avr->pc = 0;
79         for (int i = 0; i < 8; i++)
80                 avr->sreg[i] = 0;
81         if (avr->reset)
82                 avr->reset(avr);
83
84         avr_io_t * port = avr->io_port;
85         while (port) {
86                 if (port->reset)
87                         port->reset(port);
88                 port = port->next;
89         }
90 }
91
92 void avr_sadly_crashed(avr_t *avr, uint8_t signal)
93 {
94         printf("%s\n", __FUNCTION__);
95         avr->state = cpu_Stopped;
96         if (avr->gdb_port) {
97                 // enable gdb server, and wait
98                 if (!avr->gdb)
99                         avr_gdb_init(avr);
100         } 
101         if (!avr->gdb)
102                 exit(1); // no gdb ?
103 }
104
105 static void _avr_io_command_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
106 {
107         printf("%s %02x\n", __FUNCTION__, v);
108         switch (v) {
109                 case SIMAVR_CMD_VCD_START_TRACE:
110                         if (avr->vcd)
111                                 avr_vcd_start(avr->vcd);
112                         break;
113                 case SIMAVR_CMD_VCD_STOP_TRACE:
114                         if (avr->vcd)
115                                 avr_vcd_stop(avr->vcd);
116                         break;
117                 case SIMAVR_CMD_UART_LOOPBACK: {
118                         avr_irq_t * src = avr_io_getirq(avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_OUTPUT);
119                         avr_irq_t * dst = avr_io_getirq(avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_INPUT);
120                         if (src && dst) {
121                                 printf("%s activating uart local echo IRQ src %p dst %p\n", __FUNCTION__, src, dst);
122                                 avr_connect_irq(src, dst);
123                         }
124                 }       break;
125
126         }
127 }
128
129 void avr_set_command_register(avr_t * avr, avr_io_addr_t addr)
130 {
131         if (addr)
132                 avr_register_io_write(avr, addr, _avr_io_command_write, NULL);
133 }
134
135 static void _avr_io_console_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
136 {
137         static char * buf = NULL;
138         static int size = 0, len = 0;
139
140         if (v == '\r') {
141                 printf("O:" "%s" "" "\n", buf);
142                 fflush(stdout);
143         }
144         if (len + 1 >= size) {
145                 size += 128;
146                 buf = (char*)realloc(buf, size);
147         }
148         buf[len++] = v;
149 }
150
151 void avr_set_console_register(avr_t * avr, avr_io_addr_t addr)
152 {
153         if (addr)
154                 avr_register_io_write(avr, addr, _avr_io_console_write, NULL);
155 }
156
157 void avr_loadcode(avr_t * avr, uint8_t * code, uint32_t size, uint32_t address)
158 {
159         if (size > avr->flashend+1) {
160                 fprintf(stderr, "avr_loadcode(): Attempted to load code of size %d but flash size is only %d.\n",
161                         size, avr->flashend+1);
162                 abort();
163         }
164         memcpy(avr->flash + address, code, size);
165 }
166
167 void avr_callback_sleep_gdb(avr_t * avr, avr_cycle_count_t howLong)
168 {
169         uint32_t usec = avr_cycles_to_usec(avr, howLong);
170         while (avr_gdb_processor(avr, usec))
171                 ;
172 }
173
174 void avr_callback_run_gdb(avr_t * avr)
175 {
176         avr_gdb_processor(avr, avr->state == cpu_Stopped);
177
178         if (avr->state == cpu_Stopped)
179                 return ;
180
181         // if we are stepping one instruction, we "run" for one..
182         int step = avr->state == cpu_Step;
183         if (step)
184                 avr->state = cpu_Running;
185         
186         uint16_t new_pc = avr->pc;
187
188         if (avr->state == cpu_Running) {
189                 new_pc = avr_run_one(avr);
190 #if CONFIG_SIMAVR_TRACE
191                 avr_dump_state(avr);
192 #endif
193         }
194
195         // if we just re-enabled the interrupts...
196         // double buffer the I flag, to detect that edge
197         if (avr->sreg[S_I] && !avr->i_shadow)
198                 avr->pending_wait++;
199         avr->i_shadow = avr->sreg[S_I];
200
201         // run the cycle timers, get the suggested sleeo time
202         // until the next timer is due
203         avr_cycle_count_t sleep = avr_cycle_timer_process(avr);
204
205         avr->pc = new_pc;
206
207         if (avr->state == cpu_Sleeping) {
208                 if (!avr->sreg[S_I]) {
209                         printf("simavr: sleeping with interrupts off, quitting gracefully\n");
210                         avr_terminate(avr);
211                         exit(0);
212                 }
213                 /*
214                  * try to sleep for as long as we can (?)
215                  */
216                 avr->sleep(avr, sleep);
217                 avr->cycle += 1 + sleep;
218         }
219         // Interrupt servicing might change the PC too, during 'sleep'
220         if (avr->state == cpu_Running || avr->state == cpu_Sleeping)
221                 avr_service_interrupts(avr);
222         
223         // if we were stepping, use this state to inform remote gdb
224         if (step)
225                 avr->state = cpu_StepDone;
226
227 }
228
229 void avr_callback_sleep_raw(avr_t * avr, avr_cycle_count_t howLong)
230 {
231         uint32_t usec = avr_cycles_to_usec(avr, howLong);
232         usleep(usec);
233 }
234
235 void avr_callback_run_raw(avr_t * avr)
236 {
237
238         uint16_t new_pc = avr->pc;
239
240         if (avr->state == cpu_Running) {
241                 new_pc = avr_run_one(avr);
242 #if CONFIG_SIMAVR_TRACE
243                 avr_dump_state(avr);
244 #endif
245         }
246
247         // if we just re-enabled the interrupts...
248         // double buffer the I flag, to detect that edge
249         if (avr->sreg[S_I] && !avr->i_shadow)
250                 avr->pending_wait++;
251         avr->i_shadow = avr->sreg[S_I];
252
253         // run the cycle timers, get the suggested sleeo time
254         // until the next timer is due
255         avr_cycle_count_t sleep = avr_cycle_timer_process(avr);
256
257         avr->pc = new_pc;
258
259         if (avr->state == cpu_Sleeping) {
260                 if (!avr->sreg[S_I]) {
261                         printf("simavr: sleeping with interrupts off, quitting gracefully\n");
262                         avr_terminate(avr);
263                         exit(0);
264                 }
265                 /*
266                  * try to sleep for as long as we can (?)
267                  */
268                 avr->sleep(avr, sleep);
269                 avr->cycle += 1 + sleep;
270         }
271         // Interrupt servicing might change the PC too, during 'sleep'
272         if (avr->state == cpu_Running || avr->state == cpu_Sleeping)
273                 avr_service_interrupts(avr);
274 }
275
276
277 int avr_run(avr_t * avr)
278 {
279         avr->run(avr);
280         return avr->state;
281 }
282
283
284 extern avr_kind_t tiny13;
285 extern avr_kind_t tiny2313;
286 extern avr_kind_t tiny25,tiny45,tiny85;
287 extern avr_kind_t tiny24,tiny44,tiny84;
288 extern avr_kind_t mega48,mega88,mega168,mega328;
289 extern avr_kind_t mega164,mega324,mega644;
290 extern avr_kind_t mega128;
291
292 avr_kind_t * avr_kind[] = {
293         &tiny13,
294         &tiny2313,
295         &tiny25, &tiny45, &tiny85,
296         &tiny24, &tiny44, &tiny84,
297         &mega48, &mega88, &mega168, &mega328,
298         &mega164, &mega324, &mega644,
299         &mega128,
300         NULL
301 };
302
303 avr_t * avr_make_mcu_by_name(const char *name)
304 {
305         avr_kind_t * maker = NULL;
306         for (int i = 0; avr_kind[i] && !maker; i++) {
307                 for (int j = 0; avr_kind[i]->names[j]; j++)
308                         if (!strcmp(avr_kind[i]->names[j], name)) {
309                                 maker = avr_kind[i];
310                                 break;
311                         }
312         }
313         if (!maker) {
314                 fprintf(stderr, "%s: AVR '%s' now known\n", __FUNCTION__, name);
315                 return NULL;
316         }
317
318         avr_t * avr = maker->make();
319         printf("Starting %s - flashend %04x ramend %04x e2end %04x\n", avr->mmcu, avr->flashend, avr->ramend, avr->e2end);
320         return avr;     
321 }
322