Main Page

register.c
1 /*
2 * $Id: register.c,v 1.36 2008/01/06 22:38:19 joerg_wunsch Exp $
3 *
4 ****************************************************************************
5 *
6 * simulavr - A simulator for the Atmel AVR family of microcontrollers.
7 * Copyright (C) 2001, 2002, 2003, 2004 Theodore A. Roth
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 ****************************************************************************
24 */
25
26 #include <config.h>
27
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #include "avrerror.h"
32 #include "avrmalloc.h"
33 #include "avrclass.h"
34 #include "utils.h"
35 #include "callback.h"
36 #include "op_names.h"
37
38 #include "storage.h"
39 #include "flash.h"
40
41 #include "vdevs.h"
42 #include "memory.h"
43 #include "stack.h"
44 #include "register.h"
45 #include "sram.h"
46 #include "eeprom.h"
47 #include "timers.h"
48 #include "ports.h"
49
50 #include "avrcore.h"
51
52 #include "display.h"
53 #include "intvects.h"
54
55 /****************************************************************************\
56 *
57 * Status Register Methods.
58 *
59 \****************************************************************************/
60
61 static uint8_t sreg_read (VDevice *dev, int addr);
62 static void sreg_write (VDevice *dev, int addr, uint8_t val);
63 static void sreg_reset (VDevice *dev);
64 static void sreg_add_addr (VDevice *dev, int addr, char *name, int rel_addr,
65 void *data);
66
67 VDevice *
68 sreg_create (int addr, char *name, int rel_addr, void *data)
69 {
70 return (VDevice *)sreg_new ();
71 }
72
73 SREG *
74 sreg_new (void)
75 {
76 SREG *sreg;
77
78 sreg = avr_new (SREG, 1);
79 sreg_construct (sreg);
80 class_overload_destroy ((AvrClass *)sreg, sreg_destroy);
81
82 return sreg;
83 }
84
85 void
86 sreg_construct (SREG *sreg)
87 {
88 if (sreg == NULL)
89 avr_error ("passed null ptr");
90
91 vdev_construct ((VDevice *)sreg, sreg_read, sreg_write, sreg_reset,
92 sreg_add_addr);
93
94 sreg->sreg.reg = 0;
95 }
96
97 void
98 sreg_destroy (void *sreg)
99 {
100 if (sreg == NULL)
101 return;
102
103 vdev_destroy (sreg);
104 }
105
106 extern uint8_t sreg_get (SREG *sreg);
107
108 extern void sreg_set (SREG *sreg, uint8_t val);
109
110 extern uint8_t sreg_get_bit (SREG *sreg, int bit);
111
112 extern void sreg_set_bit (SREG *sreg, int bit, int val);
113
114 static uint8_t
115 sreg_read (VDevice *dev, int addr)
116 {
117 return sreg_get ((SREG *)dev);
118 }
119
120 static void
121 sreg_write (VDevice *dev, int addr, uint8_t val)
122 {
123 sreg_set ((SREG *)dev, val);
124 }
125
126 static void
127 sreg_reset (VDevice *dev)
128 {
129 display_io_reg (SREG_IO_REG, 0);
130 ((SREG *)dev)->sreg.reg = 0;
131 }
132
133 static void
134 sreg_add_addr (VDevice *dev, int addr, char *name, int rel_addr, void *data)
135 {
136 /* Nothing to do here. */
137 }
138
139
140 /****************************************************************************\
141 *
142 * General Purpose Working Register (gpwr) Methods.
143 *
144 \****************************************************************************/
145
146 static uint8_t gpwr_read (VDevice *dev, int addr);
147 static void gpwr_write (VDevice *dev, int addr, uint8_t val);
148 static void gpwr_reset (VDevice *dev);
149
150 GPWR *
151 gpwr_new (void)
152 {
153 GPWR *gpwr;
154
155 gpwr = avr_new (GPWR, 1);
156 gpwr_construct (gpwr);
157 class_overload_destroy ((AvrClass *)gpwr, gpwr_destroy);
158
159 return gpwr;
160 }
161
162 void
163 gpwr_construct (GPWR *gpwr)
164 {
165 if (gpwr == NULL)
166 avr_error ("passed null ptr");
167
168 vdev_construct ((VDevice *)gpwr, gpwr_read, gpwr_write, gpwr_reset, NULL);
169
170 gpwr_reset ((VDevice *)gpwr);
171 }
172
173 void
174 gpwr_destroy (void *gpwr)
175 {
176 if (gpwr == NULL)
177 return;
178
179 vdev_destroy (gpwr);
180 }
181
182 extern uint8_t gpwr_get (GPWR *gpwr, int reg);
183
184 extern void gpwr_set (GPWR *gpwr, int reg, uint8_t val);
185
186 static uint8_t
187 gpwr_read (VDevice *dev, int addr)
188 {
189 return gpwr_get ((GPWR *)dev, addr);
190 }
191
192 static void
193 gpwr_write (VDevice *dev, int addr, uint8_t val)
194 {
195 gpwr_set ((GPWR *)dev, addr, val);
196 }
197
198 static void
199 gpwr_reset (VDevice *dev)
200 {
201 int i;
202
203 for (i = 0; i < GPWR_SIZE; i++)
204 gpwr_set ((GPWR *)dev, i, 0);
205 }
206
207 /****************************************************************************\
208 *
209 * ACSR(VDevice) : Analog Comparator Control and Status Register Definition
210 *
211 \****************************************************************************/
212
213 static uint8_t acsr_read (VDevice *dev, int addr);
214 static void acsr_write (VDevice *dev, int addr, uint8_t val);
215 static void acsr_reset (VDevice *dev);
216
217 ACSR *
218 acsr_new (uint8_t func_mask)
219 {
220 ACSR *acsr;
221
222 acsr = avr_new (ACSR, 1);
223 acsr_construct (acsr, func_mask);
224 class_overload_destroy ((AvrClass *)acsr, acsr_destroy);
225
226 return acsr;
227 }
228
229 void
230 acsr_construct (ACSR *acsr, uint8_t func_mask)
231 {
232 if (acsr == NULL)
233 avr_error ("passed null ptr");
234
235 vdev_construct ((VDevice *)acsr, acsr_read, acsr_write, acsr_reset,
236 vdev_def_AddAddr);
237
238 acsr->func_mask = func_mask;
239 acsr->acsr = 0;
240 }
241
242 void
243 acsr_destroy (void *acsr)
244 {
245 if (acsr == NULL)
246 return;
247
248 vdev_destroy (acsr);
249 }
250
251 int
252 acsr_get_bit (ACSR *acsr, int bit)
253 {
254 return !!(acsr->acsr & acsr->func_mask & (1 << bit));
255 }
256
257 void
258 acsr_set_bit (ACSR *acsr, int bit, int val)
259 {
260 /* the ACO bit is read only */
261 acsr->acsr =
262 set_bit_in_byte (acsr->acsr, bit,
263 val) & acsr->func_mask & ~(mask_ACO);
264 }
265
266 static uint8_t
267 acsr_read (VDevice *dev, int addr)
268 {
269 ACSR *reg = (ACSR *)dev;
270
271 return (reg->acsr & reg->func_mask);
272 }
273
274 static void
275 acsr_write (VDevice *dev, int addr, uint8_t val)
276 {
277 ACSR *reg = (ACSR *)dev;
278
279 /* the ACO bit is read only */
280 reg->acsr = (val & reg->func_mask & ~(mask_ACO));
281 }
282
283 static void
284 acsr_reset (VDevice *dev)
285 {
286 ((ACSR *)dev)->acsr = 0;
287 }
288
289 /****************************************************************************\
290 *
291 * MCUCR(VDevice) : MCU general control register
292 *
293 \****************************************************************************/
294
295 static uint8_t mcucr_read (VDevice *dev, int addr);
296 static void mcucr_write (VDevice *dev, int addr, uint8_t val);
297 static void mcucr_reset (VDevice *dev);
298
299 MCUCR *
300 mcucr_new (uint8_t func_mask)
301 {
302 MCUCR *mcucr;
303
304 mcucr = avr_new (MCUCR, 1);
305 mcucr_construct (mcucr, func_mask);
306 class_overload_destroy ((AvrClass *)mcucr, mcucr_destroy);
307
308 return mcucr;
309 }
310
311 void
312 mcucr_construct (MCUCR *mcucr, uint8_t func_mask)
313 {
314 if (mcucr == NULL)
315 avr_error ("passed null ptr");
316
317 vdev_construct ((VDevice *)mcucr, mcucr_read, mcucr_write, mcucr_reset,
318 vdev_def_AddAddr);
319
320 mcucr->func_mask = func_mask;
321 mcucr->mcucr = 0;
322 }
323
324 void
325 mcucr_destroy (void *mcucr)
326 {
327 if (mcucr == NULL)
328 return;
329
330 vdev_destroy (mcucr);
331 }
332
333 int
334 mcucr_get_bit (MCUCR *reg, int bit)
335 {
336 return !!(reg->mcucr & reg->func_mask & (1 << bit));
337 }
338
339 void
340 mcucr_set_bit (MCUCR *reg, int bit, int val)
341 {
342 reg->mcucr = set_bit_in_byte (reg->mcucr, bit, val) & reg->func_mask;
343 }
344
345 static uint8_t
346 mcucr_read (VDevice *dev, int addr)
347 {
348 MCUCR *reg = (MCUCR *)dev;
349
350 return (reg->mcucr & reg->func_mask);
351 }
352
353 static void
354 mcucr_write (VDevice *dev, int addr, uint8_t val)
355 {
356 MCUCR *reg = (MCUCR *)dev;
357
358 reg->mcucr = (val & reg->func_mask);
359 }
360
361 static void
362 mcucr_reset (VDevice *dev)
363 {
364 ((MCUCR *)dev)->mcucr = 0;
365 }
366
367 /****************************************************************************\
368 *
369 * WDTCR(VDevice) : Watchdog timer control register
370 *
371 \****************************************************************************/
372
373 /* static int wdtcr_get_bit ( WDTCR *wdtcr, int bit ); */
374 static void wdtcr_set_bit (WDTCR *wdtcr, int bit, int val);
375
376 static uint8_t wdtcr_read (VDevice *dev, int addr);
377 static void wdtcr_write (VDevice *dev, int addr, uint8_t val);
378 static void wdtcr_reset (VDevice *dev);
379
380 static int wdtcr_timer_cb (uint64_t time, AvrClass *data);
381 static int wdtcr_toe_clr_cb (uint64_t time, AvrClass *data);
382
383 WDTCR *
384 wdtcr_new (uint8_t func_mask)
385 {
386 WDTCR *wdtcr;
387
388 wdtcr = avr_new (WDTCR, 1);
389 wdtcr_construct (wdtcr, func_mask);
390 class_overload_destroy ((AvrClass *)wdtcr, wdtcr_destroy);
391
392 return wdtcr;
393 }
394
395 void
396 wdtcr_construct (WDTCR *wdtcr, uint8_t func_mask)
397 {
398 if (wdtcr == NULL)
399 avr_error ("passed null ptr");
400
401 vdev_construct ((VDevice *)wdtcr, wdtcr_read, wdtcr_write, wdtcr_reset,
402 vdev_def_AddAddr);
403
404 wdtcr->func_mask = func_mask;
405
406 wdtcr_reset ((VDevice *)wdtcr);
407 }
408
409 void
410 wdtcr_destroy (void *wdtcr)
411 {
412 if (wdtcr == NULL)
413 return;
414
415 vdev_destroy (wdtcr);
416 }
417
418 /*
419 * Function wdtcr_update: Called when the WDR instruction is issued
420 */
421 void
422 wdtcr_update (WDTCR *wdtcr)
423 {
424 wdtcr->last_WDR = get_program_time ();
425 }
426
427 #if 0 /* This doesn't seem to be used anywhere. */
428 static int
429 wdtcr_get_bit (WDTCR *reg, int bit)
430 {
431 return !!(reg->wdtcr & reg->func_mask & (1 << bit));
432 }
433 #endif
434
435 static void
436 wdtcr_set_bit (WDTCR *reg, int bit, int val)
437 {
438 reg->wdtcr = set_bit_in_byte (reg->wdtcr, bit, val) & reg->func_mask;
439 }
440
441 static uint8_t
442 wdtcr_read (VDevice *dev, int addr)
443 {
444 WDTCR *reg = (WDTCR *)dev;
445
446 return (reg->wdtcr & reg->func_mask);
447 }
448
449 /*
450 * FIXME: Should the wdtcr->toe_clk counter be reset to TOE_CLKS
451 * every time a WDTOE is set 1? I.E. does the hw reset the 4 cycle
452 * counter every time WDTOE is set? This code assumes it does.
453 */
454 static void
455 wdtcr_write (VDevice *dev, int addr, uint8_t val)
456 {
457 WDTCR *reg = (WDTCR *)dev;
458 uint8_t wd_enabled = (reg->wdtcr & mask_WDE);
459
460 CallBack *cb;
461
462 if (reg->func_mask & mask_WDTOE)
463 { /* Device has WDTOE functionality */
464
465 if ((reg->wdtcr & mask_WDE) && !(reg->wdtcr & mask_WDTOE))
466 {
467 /* WDE can _NOT_ be cleared if WDTOE is zero */
468 val |= mask_WDE;
469 }
470
471 if (val & mask_WDTOE)
472 { /* program has set WDTOE */
473 reg->toe_clk = TOE_CLKS;
474
475 /* create and install the callback if it not already installed */
476 if (reg->toe_cb == NULL)
477 {
478 cb = callback_new (wdtcr_toe_clr_cb, (AvrClass *)reg);
479 reg->toe_cb = cb;
480 avr_core_clk_cb_add ((AvrCore *)vdev_get_core (dev), cb);
481 }
482 }
483 }
484
485 reg->wdtcr = (val & reg->func_mask);
486
487 if ((wd_enabled == 0) && (val & mask_WDE) && (reg->timer_cb == NULL))
488 {
489 /* install the WD timer callback */
490 cb = callback_new (wdtcr_timer_cb, (AvrClass *)reg);
491 reg->timer_cb = cb;
492 avr_core_async_cb_add ((AvrCore *)vdev_get_core (dev), cb);
493 }
494
495 if (wd_enabled && ((val & mask_WDE) == 0) && (reg->timer_cb != NULL))
496 {
497 /* tell callback to remove itself */
498 reg->timer_cb = NULL;
499 }
500 }
501
502 static void
503 wdtcr_reset (VDevice *dev)
504 {
505 WDTCR *wdtcr = (WDTCR *)dev;
506
507 wdtcr->wdtcr = 0;
508
509 wdtcr->last_WDR = get_program_time (); /* FIXME: This might not be the
510 right thing to do */
511 wdtcr->timer_cb = NULL;
512
513 wdtcr->toe_clk = TOE_CLKS;
514 wdtcr->toe_cb = NULL;
515 }
516
517 /*
518 * Timer callback will remove itself if wdtcr->timer_cb is set NULL.
519 */
520 static int
521 wdtcr_timer_cb (uint64_t time, AvrClass *data)
522 {
523 WDTCR *wdtcr = (WDTCR *)data;
524 uint64_t time_diff;
525 uint64_t time_out;
526
527 if (wdtcr->timer_cb == NULL)
528 return CB_RET_REMOVE;
529
530 time_diff = time - wdtcr->last_WDR;
531 time_out = TIMEOUT_BASE * (1 << (wdtcr->wdtcr & mask_WDP));
532
533 if (time_diff > time_out)
534 {
535 avr_warning ("watchdog reset: time %lld\n", time_diff);
536
537 /* reset the device, we timed out */
538 avr_core_irq_raise ((AvrCore *)vdev_get_core ((VDevice *)wdtcr),
539 irq_vect_table_index (RESET));
540 }
541
542 return CB_RET_RETAIN;
543 }
544
545 /*
546 * The WDTOE is cleared by hardware after TOE_CLKS clock cycles.
547 */
548 static int
549 wdtcr_toe_clr_cb (uint64_t time, AvrClass *data)
550 {
551 WDTCR *wdtcr = (WDTCR *)data;
552
553 if (wdtcr->toe_cb == NULL)
554 return CB_RET_REMOVE;
555
556 if (wdtcr->toe_clk > 0)
557 {
558 wdtcr->toe_clk--;
559 }
560 else
561 {
562 wdtcr_set_bit (wdtcr, bit_WDTOE, 0);
563 wdtcr->toe_cb = NULL; /* So we know that cb is not installed */
564 return CB_RET_REMOVE;
565 }
566
567 return CB_RET_RETAIN;
568 }
569
570 /****************************************************************************\
571 *
572 * RAMPZ(VDevice) : The RAMPZ register used by ELPM and ESPM instructions.
573 *
574 * Even though the rampz register is not available to all devices, we will
575 * install it for all in the simulator. It just so much easier that way and
576 * we're already assuming that the compiler generated the correct code in
577 * many places anyways. Let's see if we get bit.
578 *
579 \****************************************************************************/
580
581 static uint8_t rampz_read (VDevice *dev, int addr);
582 static void rampz_write (VDevice *dev, int addr, uint8_t val);
583 static void rampz_reset (VDevice *dev);
584
585 VDevice *
586 rampz_create (int addr, char *name, int rel_addr, void *data)
587 {
588 return (VDevice *)rampz_new ();
589 }
590
591 RAMPZ *
592 rampz_new (void)
593 {
594 RAMPZ *rampz;
595
596 rampz = avr_new (RAMPZ, 1);
597 rampz_construct (rampz);
598 class_overload_destroy ((AvrClass *)rampz, rampz_destroy);
599
600 return rampz;
601 }
602
603 void
604 rampz_construct (RAMPZ *rampz)
605 {
606 if (rampz == NULL)
607 avr_error ("passed null ptr");
608
609 vdev_construct ((VDevice *)rampz, rampz_read, rampz_write, rampz_reset,
610 vdev_def_AddAddr);
611
612 rampz->reg = 0;
613 }
614
615 void
616 rampz_destroy (void *rampz)
617 {
618 if (rampz == NULL)
619 return;
620
621 vdev_destroy (rampz);
622 }
623
624 uint8_t
625 rampz_get (RAMPZ *rampz)
626 {
627 return rampz->reg;
628 }
629
630 void
631 rampz_set (RAMPZ *rampz, uint8_t val)
632 {
633 rampz->reg = val;
634 }
635
636 static uint8_t
637 rampz_read (VDevice *dev, int addr)
638 {
639 return rampz_get ((RAMPZ *)dev);
640 }
641
642 static void
643 rampz_write (VDevice *dev, int addr, uint8_t val)
644 {
645 rampz_set ((RAMPZ *)dev, val);
646 }
647
648 static void
649 rampz_reset (VDevice *dev)
650 {
651 display_io_reg (RAMPZ_IO_REG, 0);
652 ((RAMPZ *)dev)->reg = 0;
653 }
avr_new
#define avr_new(type, count)
Macro for allocating memory.
Definition: avrmalloc.c:57
get_program_time
uint64_t get_program_time(void)
Return the number of milliseconds of elapsed program time.
Definition: utils.c:76
avr_core_async_cb_add
void avr_core_async_cb_add(AvrCore *core, CallBack *cb)
Add a new asynchronous callback to list.
vdev_def_AddAddr
void vdev_def_AddAddr(VDevice *dev, int addr, char *name, int related_addr, void *data)
Default AddAddr method.
Definition: device.c:80
vdev_destroy
void vdev_destroy(void *dev)
Destructor for a VDevice.
Definition: device.c:105
avr_core_irq_raise
void avr_core_irq_raise(AvrCore *core, unsigned int irq)
Raises an irq by adding it&#39;s data to the irq_pending list.
Definition: avrcore.c:854
vdev_get_core
AvrClass * vdev_get_core(VDevice *dev)
Get the core field.
set_bit_in_byte
uint8_t set_bit_in_byte(uint8_t src, int bit, int val)
Set a bit in src to 1 if val != 0, clears bit if val == 0.
avr_warning
#define avr_warning(fmt, args...)
Print a warning message to stderr.
Definition: avrerror.c:46
vdev_construct
void vdev_construct(VDevice *dev, VDevFP_Read rd, VDevFP_Write wr, VDevFP_Reset reset, VDevFP_AddAddr add_addr)
Constructor for a VDevice.
Definition: device.c:89
avr_error
#define avr_error(fmt, args...)
Print an error message to stderr and terminate program.
Definition: avrerror.c:50
avr_core_clk_cb_add
void avr_core_clk_cb_add(AvrCore *core, CallBack *cb)
Add a new clock callback to list.
display_io_reg
void display_io_reg(int reg, uint8_t val)
Update an IO register in the display.
Definition: display.c:299
class_overload_destroy
void class_overload_destroy(AvrClass *klass, AvrClassFP_Destroy destroy)
Overload the default destroy method.
Definition: avrclass.c:92

Automatically generated by Doxygen 1.8.12 on Tue Apr 18 2017.