core: Add an overridable logging function
[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 <stdarg.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include "sim_avr.h"
28 #include "sim_core.h"
29 #include "sim_time.h"
30 #include "sim_gdb.h"
31 #include "avr_uart.h"
32 #include "sim_vcd_file.h"
33 #include "avr/avr_mcu_section.h"
34
35 #define AVR_KIND_DECL
36 #include "sim_core_decl.h"
37
38 static void std_logger(avr_t * avr, const int level, const char * format, ...);
39 logger_t global_logger = std_logger;
40
41 int avr_init(avr_t * avr)
42 {
43         avr->flash = malloc(avr->flashend + 1);
44         memset(avr->flash, 0xff, avr->flashend + 1);
45         avr->data = malloc(avr->ramend + 1);
46         memset(avr->data, 0, avr->ramend + 1);
47 #ifdef CONFIG_SIMAVR_TRACE
48         avr->trace_data = calloc(1, sizeof(struct avr_trace_data_t));
49 #endif
50         
51         AVR_LOG(avr, LOG_TRACE, "%s init\n", avr->mmcu);
52
53         // cpu is in limbo before init is finished.
54         avr->state = cpu_Limbo;
55         avr->frequency = 1000000;       // can be overridden via avr_mcu_section
56         if (avr->special_init)
57                 avr->special_init(avr);
58         if (avr->init)
59                 avr->init(avr);
60         // set default (non gdb) fast callbacks
61         avr->run = avr_callback_run_raw;
62         avr->sleep = avr_callback_sleep_raw;
63         avr->state = cpu_Running;
64         avr->log = 1;
65         avr_reset(avr); 
66         return 0;
67 }
68
69 void avr_terminate(avr_t * avr)
70 {
71         if (avr->special_deinit)
72                 avr->special_deinit(avr);
73         if (avr->gdb) {
74                 avr_deinit_gdb(avr);
75                 avr->gdb = NULL;
76         }
77         if (avr->vcd) {
78                 avr_vcd_close(avr->vcd);
79                 avr->vcd = NULL;
80         }
81         avr_deallocate_ios(avr);
82
83         if (avr->flash) free(avr->flash);
84         if (avr->data) free(avr->data);
85         avr->flash = avr->data = NULL;
86 }
87
88 void avr_reset(avr_t * avr)
89 {
90         AVR_LOG(avr, LOG_TRACE, "%s reset\n", avr->mmcu);
91
92         memset(avr->data, 0x0, avr->ramend + 1);
93         _avr_sp_set(avr, avr->ramend);
94         avr->pc = 0;
95         for (int i = 0; i < 8; i++)
96                 avr->sreg[i] = 0;
97         if (avr->reset)
98                 avr->reset(avr);
99         avr_interrupt_reset(avr);
100         avr_cycle_timer_reset(avr);
101         avr_io_t * port = avr->io_port;
102         while (port) {
103                 if (port->reset)
104                         port->reset(port);
105                 port = port->next;
106         }
107 }
108
109 void avr_sadly_crashed(avr_t *avr, uint8_t signal)
110 {
111         AVR_LOG(avr, LOG_ERROR, "%s\n", __FUNCTION__);
112         avr->state = cpu_Stopped;
113         if (avr->gdb_port) {
114                 // enable gdb server, and wait
115                 if (!avr->gdb)
116                         avr_gdb_init(avr);
117         } 
118         if (!avr->gdb)
119                 avr->state = cpu_Crashed;
120 }
121
122 static void _avr_io_command_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
123 {
124         AVR_LOG(avr, LOG_TRACE, "%s %02x\n", __FUNCTION__, v);
125         switch (v) {
126                 case SIMAVR_CMD_VCD_START_TRACE:
127                         if (avr->vcd)
128                                 avr_vcd_start(avr->vcd);
129                         break;
130                 case SIMAVR_CMD_VCD_STOP_TRACE:
131                         if (avr->vcd)
132                                 avr_vcd_stop(avr->vcd);
133                         break;
134                 case SIMAVR_CMD_UART_LOOPBACK: {
135                         avr_irq_t * src = avr_io_getirq(avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_OUTPUT);
136                         avr_irq_t * dst = avr_io_getirq(avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_INPUT);
137                         if (src && dst) {
138                                 AVR_LOG(avr, LOG_TRACE, "%s activating uart local echo IRQ src %p dst %p\n",
139                                                 __FUNCTION__, src, dst);
140                                 avr_connect_irq(src, dst);
141                         }
142                 }       break;
143
144         }
145 }
146
147 void avr_set_command_register(avr_t * avr, avr_io_addr_t addr)
148 {
149         if (addr)
150                 avr_register_io_write(avr, addr, _avr_io_command_write, NULL);
151 }
152
153 static void _avr_io_console_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
154 {
155         static char * buf = NULL;
156         static int size = 0, len = 0;
157
158         if (v == '\r' && buf) {
159                 buf[len] = 0;
160                 AVR_LOG(avr, LOG_TRACE, "O:" "%s" "" "\n", buf);
161                 fflush(stdout);
162                 len = 0;
163                 return;
164         }
165         if (len + 1 >= size) {
166                 size += 128;
167                 buf = (char*)realloc(buf, size);
168         }
169         if (v >= ' ')
170                 buf[len++] = v;
171 }
172
173 void avr_set_console_register(avr_t * avr, avr_io_addr_t addr)
174 {
175         if (addr)
176                 avr_register_io_write(avr, addr, _avr_io_console_write, NULL);
177 }
178
179 void avr_loadcode(avr_t * avr, uint8_t * code, uint32_t size, avr_flashaddr_t address)
180 {
181         if (size > avr->flashend+1) {
182                 AVR_LOG(avr, LOG_ERROR, "avr_loadcode(): Attempted to load code of size %d but flash size is only %d.\n",
183                         size, avr->flashend + 1);
184                 abort();
185         }
186         memcpy(avr->flash + address, code, size);
187 }
188
189 /**
190  * Accumulates sleep requests (and returns a sleep time of 0) until
191  * a minimum count of requested sleep microseconds are reached
192  * (low amounts cannot be handled accurately).
193  */
194 static inline uint32_t avr_pending_sleep_usec(avr_t * avr, avr_cycle_count_t howLong)
195 {
196         avr->sleep_usec += avr_cycles_to_usec(avr, howLong);
197         uint32_t usec = avr->sleep_usec;
198         if (usec > 200) {
199                 avr->sleep_usec = 0;
200                 return usec;
201         }
202         return 0;
203 }
204
205 void avr_callback_sleep_gdb(avr_t * avr, avr_cycle_count_t howLong)
206 {
207         uint32_t usec = avr_pending_sleep_usec(avr, howLong);
208         while (avr_gdb_processor(avr, usec))
209                 ;
210 }
211
212 void avr_callback_run_gdb(avr_t * avr)
213 {
214         avr_gdb_processor(avr, avr->state == cpu_Stopped);
215
216         if (avr->state == cpu_Stopped)
217                 return ;
218
219         // if we are stepping one instruction, we "run" for one..
220         int step = avr->state == cpu_Step;
221         if (step)
222                 avr->state = cpu_Running;
223         
224         avr_flashaddr_t new_pc = avr->pc;
225
226         if (avr->state == cpu_Running) {
227                 new_pc = avr_run_one(avr);
228 #if CONFIG_SIMAVR_TRACE
229                 avr_dump_state(avr);
230 #endif
231         }
232
233         // if we just re-enabled the interrupts...
234         // double buffer the I flag, to detect that edge
235         if (avr->sreg[S_I] && !avr->i_shadow)
236                 avr->interrupts.pending_wait++;
237         avr->i_shadow = avr->sreg[S_I];
238
239         // run the cycle timers, get the suggested sleep time
240         // until the next timer is due
241         avr_cycle_count_t sleep = avr_cycle_timer_process(avr);
242
243         avr->pc = new_pc;
244
245         if (avr->state == cpu_Sleeping) {
246                 if (!avr->sreg[S_I]) {
247                         if (avr->log)
248                                 AVR_LOG(avr, LOG_TRACE, "simavr: sleeping with interrupts off, quitting gracefully\n");
249                         avr->state = cpu_Done;
250                         return;
251                 }
252                 /*
253                  * try to sleep for as long as we can (?)
254                  */
255                 avr->sleep(avr, sleep);
256                 avr->cycle += 1 + sleep;
257         }
258         // Interrupt servicing might change the PC too, during 'sleep'
259         if (avr->state == cpu_Running || avr->state == cpu_Sleeping)
260                 avr_service_interrupts(avr);
261         
262         // if we were stepping, use this state to inform remote gdb
263         if (step)
264                 avr->state = cpu_StepDone;
265
266 }
267
268 void avr_callback_sleep_raw(avr_t * avr, avr_cycle_count_t howLong)
269 {
270         uint32_t usec = avr_pending_sleep_usec(avr, howLong);
271         if (usec > 0) {
272                 usleep(usec);
273         }
274 }
275
276 void avr_callback_run_raw(avr_t * avr)
277 {
278         avr_flashaddr_t new_pc = avr->pc;
279
280         if (avr->state == cpu_Running) {
281                 new_pc = avr_run_one(avr);
282 #if CONFIG_SIMAVR_TRACE
283                 avr_dump_state(avr);
284 #endif
285         }
286
287         // if we just re-enabled the interrupts...
288         // double buffer the I flag, to detect that edge
289         if (avr->sreg[S_I] && !avr->i_shadow)
290                 avr->interrupts.pending_wait++;
291         avr->i_shadow = avr->sreg[S_I];
292
293         // run the cycle timers, get the suggested sleep time
294         // until the next timer is due
295         avr_cycle_count_t sleep = avr_cycle_timer_process(avr);
296
297         avr->pc = new_pc;
298
299         if (avr->state == cpu_Sleeping) {
300                 if (!avr->sreg[S_I]) {
301                         if (avr->log)
302                                 AVR_LOG(avr, LOG_TRACE, "simavr: sleeping with interrupts off, quitting gracefully\n");
303                         avr->state = cpu_Done;
304                         return;
305                 }
306                 /*
307                  * try to sleep for as long as we can (?)
308                  */
309                 avr->sleep(avr, sleep);
310                 avr->cycle += 1 + sleep;
311         }
312         // Interrupt servicing might change the PC too, during 'sleep'
313         if (avr->state == cpu_Running || avr->state == cpu_Sleeping)
314                 avr_service_interrupts(avr);
315 }
316
317
318 int avr_run(avr_t * avr)
319 {
320         avr->run(avr);
321         return avr->state;
322 }
323
324 avr_t *
325 avr_core_allocate(
326                 const avr_t * core,
327                 uint32_t coreLen)
328 {
329         uint8_t * b = malloc(coreLen);
330         memcpy(b, core, coreLen);
331         return (avr_t *)b;
332 }
333
334 avr_t *
335 avr_make_mcu_by_name(
336                 const char *name)
337 {
338         avr_kind_t * maker = NULL;
339         for (int i = 0; avr_kind[i] && !maker; i++) {
340                 for (int j = 0; avr_kind[i]->names[j]; j++)
341                         if (!strcmp(avr_kind[i]->names[j], name)) {
342                                 maker = avr_kind[i];
343                                 break;
344                         }
345         }
346         if (!maker) {
347                 AVR_LOG(((avr_t*)0), LOG_ERROR, "%s: AVR '%s' not known\n", __FUNCTION__, name);
348                 return NULL;
349         }
350
351         avr_t * avr = maker->make();
352         AVR_LOG(avr, LOG_TRACE, "Starting %s - flashend %04x ramend %04x e2end %04x\n",
353                         avr->mmcu, avr->flashend, avr->ramend, avr->e2end);
354         return avr;
355 }
356
357 static void std_logger(avr_t* avr, const int level, const char * format, ...)
358 {
359         if (!avr || avr->log >= level) {
360                 va_list args;
361                 va_start(args, format);
362                 vfprintf((level > LOG_ERROR) ?  stdout : stderr , format, args);
363                 va_end(args);
364         }
365 }
366