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,
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,
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,
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,
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 }

Automatically generated by Doxygen 1.8.2 on Wed Mar 12 2014.