Main Page | File List | Globals | Related Pages

register.c

00001 /* 00002 * $Id: register.c,v 1.33 2003/12/01 09:10:16 troth Exp $ 00003 * 00004 **************************************************************************** 00005 * 00006 * simulavr - A simulator for the Atmel AVR family of microcontrollers. 00007 * Copyright (C) 2001, 2002, 2003 Theodore A. Roth 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 * 00023 **************************************************************************** 00024 */ 00025 00026 #include <config.h> 00027 00028 #include <stdio.h> 00029 #include <stdlib.h> 00030 00031 #include "avrerror.h" 00032 #include "avrmalloc.h" 00033 #include "avrclass.h" 00034 #include "utils.h" 00035 #include "callback.h" 00036 #include "op_names.h" 00037 00038 #include "storage.h" 00039 #include "flash.h" 00040 00041 #include "vdevs.h" 00042 #include "memory.h" 00043 #include "stack.h" 00044 #include "register.h" 00045 #include "sram.h" 00046 #include "eeprom.h" 00047 #include "timers.h" 00048 #include "ports.h" 00049 00050 #include "avrcore.h" 00051 00052 #include "display.h" 00053 #include "intvects.h" 00054 00055 /****************************************************************************\ 00056 * 00057 * Status Register Methods. 00058 * 00059 \****************************************************************************/ 00060 00061 static inline uint8_t sreg_read (VDevice *dev, int addr); 00062 static inline void sreg_write (VDevice *dev, int addr, uint8_t val); 00063 static inline void sreg_reset (VDevice *dev); 00064 static inline char *sreg_reg_name (VDevice *dev, int addr); 00065 00066 SREG * 00067 sreg_new (void) 00068 { 00069 SREG *sreg; 00070 00071 sreg = avr_new (SREG, 1); 00072 sreg_construct (sreg); 00073 class_overload_destroy ((AvrClass *)sreg, sreg_destroy); 00074 00075 return sreg; 00076 } 00077 00078 void 00079 sreg_construct (SREG *sreg) 00080 { 00081 char *name = "SREG"; 00082 00083 if (sreg == NULL) 00084 avr_error ("passed null ptr"); 00085 00086 vdev_construct ((VDevice *)sreg, name, SREG_BASE, SREG_SIZE, sreg_read, 00087 sreg_write, sreg_reset, sreg_reg_name); 00088 00089 sreg->sreg.reg = 0; 00090 } 00091 00092 void 00093 sreg_destroy (void *sreg) 00094 { 00095 if (sreg == NULL) 00096 return; 00097 00098 vdev_destroy (sreg); 00099 } 00100 00101 extern inline uint8_t sreg_get (SREG *sreg); 00102 00103 extern inline void sreg_set (SREG *sreg, uint8_t val); 00104 00105 extern inline uint8_t sreg_get_bit (SREG *sreg, int bit); 00106 00107 extern inline void sreg_set_bit (SREG *sreg, int bit, int val); 00108 00109 static inline uint8_t 00110 sreg_read (VDevice *dev, int addr) 00111 { 00112 return sreg_get ((SREG *)dev); 00113 } 00114 00115 static inline void 00116 sreg_write (VDevice *dev, int addr, uint8_t val) 00117 { 00118 sreg_set ((SREG *)dev, val); 00119 } 00120 00121 static inline void 00122 sreg_reset (VDevice *dev) 00123 { 00124 display_io_reg (SREG_IO_REG, 0); 00125 ((SREG *)dev)->sreg.reg = 0; 00126 } 00127 00128 static inline char * 00129 sreg_reg_name (VDevice *dev, int addr) 00130 { 00131 return vdev_get_name (dev); 00132 } 00133 00134 /****************************************************************************\ 00135 * 00136 * General Purpose Working Register (gpwr) Methods. 00137 * 00138 \****************************************************************************/ 00139 00140 static inline uint8_t gpwr_read (VDevice *dev, int addr); 00141 static inline void gpwr_write (VDevice *dev, int addr, uint8_t val); 00142 static inline void gpwr_reset (VDevice *dev); 00143 00144 GPWR * 00145 gpwr_new (void) 00146 { 00147 GPWR *gpwr; 00148 00149 gpwr = avr_new (GPWR, 1); 00150 gpwr_construct (gpwr); 00151 class_overload_destroy ((AvrClass *)gpwr, gpwr_destroy); 00152 00153 return gpwr; 00154 } 00155 00156 void 00157 gpwr_construct (GPWR *gpwr) 00158 { 00159 char *name = "GPWR"; 00160 00161 if (gpwr == NULL) 00162 avr_error ("passed null ptr"); 00163 00164 vdev_construct ((VDevice *)gpwr, name, GPWR_BASE, GPWR_SIZE, gpwr_read, 00165 gpwr_write, gpwr_reset, NULL); 00166 00167 gpwr_reset ((VDevice *)gpwr); 00168 } 00169 00170 void 00171 gpwr_destroy (void *gpwr) 00172 { 00173 if (gpwr == NULL) 00174 return; 00175 00176 vdev_destroy (gpwr); 00177 } 00178 00179 extern inline uint8_t gpwr_get (GPWR *gpwr, int reg); 00180 00181 extern inline void gpwr_set (GPWR *gpwr, int reg, uint8_t val); 00182 00183 static inline uint8_t 00184 gpwr_read (VDevice *dev, int addr) 00185 { 00186 return gpwr_get ((GPWR *)dev, addr); 00187 } 00188 00189 static inline void 00190 gpwr_write (VDevice *dev, int addr, uint8_t val) 00191 { 00192 gpwr_set ((GPWR *)dev, addr, val); 00193 } 00194 00195 static void 00196 gpwr_reset (VDevice *dev) 00197 { 00198 int i; 00199 00200 for (i = 0; i < GPWR_SIZE; i++) 00201 gpwr_set ((GPWR *)dev, i, 0); 00202 } 00203 00204 /****************************************************************************\ 00205 * 00206 * ACSR(VDevice) : Analog Comparator Control and Status Register Definition 00207 * 00208 \****************************************************************************/ 00209 00210 static uint8_t acsr_read (VDevice *dev, int addr); 00211 static void acsr_write (VDevice *dev, int addr, uint8_t val); 00212 static void acsr_reset (VDevice *dev); 00213 static char *acsr_reg_name (VDevice *dev, int addr); 00214 00215 ACSR * 00216 acsr_new (uint8_t func_mask) 00217 { 00218 ACSR *acsr; 00219 00220 acsr = avr_new (ACSR, 1); 00221 acsr_construct (acsr, func_mask); 00222 class_overload_destroy ((AvrClass *)acsr, acsr_destroy); 00223 00224 return acsr; 00225 } 00226 00227 void 00228 acsr_construct (ACSR *acsr, uint8_t func_mask) 00229 { 00230 char *name = "ACSR"; 00231 00232 if (acsr == NULL) 00233 avr_error ("passed null ptr"); 00234 00235 vdev_construct ((VDevice *)acsr, name, ACSR_BASE, ACSR_SIZE, acsr_read, 00236 acsr_write, acsr_reset, acsr_reg_name); 00237 00238 acsr->func_mask = func_mask; 00239 acsr->acsr = 0; 00240 } 00241 00242 void 00243 acsr_destroy (void *acsr) 00244 { 00245 if (acsr == NULL) 00246 return; 00247 00248 vdev_destroy (acsr); 00249 } 00250 00251 int 00252 acsr_get_bit (ACSR *acsr, int bit) 00253 { 00254 return !!(acsr->acsr & acsr->func_mask & (1 << bit)); 00255 } 00256 00257 void 00258 acsr_set_bit (ACSR *acsr, int bit, int val) 00259 { 00260 /* the ACO bit is read only */ 00261 acsr->acsr = 00262 set_bit_in_byte (acsr->acsr, bit, 00263 val) & acsr->func_mask & ~(mask_ACO); 00264 } 00265 00266 static uint8_t 00267 acsr_read (VDevice *dev, int addr) 00268 { 00269 ACSR *reg = (ACSR *)dev; 00270 00271 return (reg->acsr & reg->func_mask); 00272 } 00273 00274 static void 00275 acsr_write (VDevice *dev, int addr, uint8_t val) 00276 { 00277 ACSR *reg = (ACSR *)dev; 00278 00279 /* the ACO bit is read only */ 00280 reg->acsr = (val & reg->func_mask & ~(mask_ACO)); 00281 } 00282 00283 static void 00284 acsr_reset (VDevice *dev) 00285 { 00286 ((ACSR *)dev)->acsr = 0; 00287 } 00288 00289 static char * 00290 acsr_reg_name (VDevice *dev, int addr) 00291 { 00292 return vdev_get_name (dev); 00293 } 00294 00295 /****************************************************************************\ 00296 * 00297 * MCUCR(VDevice) : MCU general control register 00298 * 00299 \****************************************************************************/ 00300 00301 static uint8_t mcucr_read (VDevice *dev, int addr); 00302 static void mcucr_write (VDevice *dev, int addr, uint8_t val); 00303 static void mcucr_reset (VDevice *dev); 00304 static char *mcucr_reg_name (VDevice *dev, int addr); 00305 00306 MCUCR * 00307 mcucr_new (uint8_t func_mask) 00308 { 00309 MCUCR *mcucr; 00310 00311 mcucr = avr_new (MCUCR, 1); 00312 mcucr_construct (mcucr, func_mask); 00313 class_overload_destroy ((AvrClass *)mcucr, mcucr_destroy); 00314 00315 return mcucr; 00316 } 00317 00318 void 00319 mcucr_construct (MCUCR *mcucr, uint8_t func_mask) 00320 { 00321 char *name = "MCUCR"; 00322 00323 if (mcucr == NULL) 00324 avr_error ("passed null ptr"); 00325 00326 vdev_construct ((VDevice *)mcucr, name, MCUCR_BASE, MCUCR_SIZE, 00327 mcucr_read, mcucr_write, mcucr_reset, mcucr_reg_name); 00328 00329 mcucr->func_mask = func_mask; 00330 mcucr->mcucr = 0; 00331 } 00332 00333 void 00334 mcucr_destroy (void *mcucr) 00335 { 00336 if (mcucr == NULL) 00337 return; 00338 00339 vdev_destroy (mcucr); 00340 } 00341 00342 int 00343 mcucr_get_bit (MCUCR *reg, int bit) 00344 { 00345 return !!(reg->mcucr & reg->func_mask & (1 << bit)); 00346 } 00347 00348 void 00349 mcucr_set_bit (MCUCR *reg, int bit, int val) 00350 { 00351 reg->mcucr = set_bit_in_byte (reg->mcucr, bit, val) & reg->func_mask; 00352 } 00353 00354 static uint8_t 00355 mcucr_read (VDevice *dev, int addr) 00356 { 00357 MCUCR *reg = (MCUCR *)dev; 00358 00359 return (reg->mcucr & reg->func_mask); 00360 } 00361 00362 static void 00363 mcucr_write (VDevice *dev, int addr, uint8_t val) 00364 { 00365 MCUCR *reg = (MCUCR *)dev; 00366 00367 reg->mcucr = (val & reg->func_mask); 00368 } 00369 00370 static void 00371 mcucr_reset (VDevice *dev) 00372 { 00373 ((MCUCR *)dev)->mcucr = 0; 00374 } 00375 00376 static char * 00377 mcucr_reg_name (VDevice *dev, int addr) 00378 { 00379 return vdev_get_name (dev); 00380 } 00381 00382 /****************************************************************************\ 00383 * 00384 * WDTCR(VDevice) : Watchdog timer control register 00385 * 00386 \****************************************************************************/ 00387 00388 /* static int wdtcr_get_bit ( WDTCR *wdtcr, int bit ); */ 00389 static void wdtcr_set_bit (WDTCR *wdtcr, int bit, int val); 00390 00391 static uint8_t wdtcr_read (VDevice *dev, int addr); 00392 static void wdtcr_write (VDevice *dev, int addr, uint8_t val); 00393 static void wdtcr_reset (VDevice *dev); 00394 static char *wdtcr_reg_name (VDevice *dev, int addr); 00395 00396 static int wdtcr_timer_cb (uint64_t time, AvrClass *data); 00397 static int wdtcr_toe_clr_cb (uint64_t time, AvrClass *data); 00398 00399 WDTCR * 00400 wdtcr_new (uint8_t func_mask) 00401 { 00402 WDTCR *wdtcr; 00403 00404 wdtcr = avr_new (WDTCR, 1); 00405 wdtcr_construct (wdtcr, func_mask); 00406 class_overload_destroy ((AvrClass *)wdtcr, wdtcr_destroy); 00407 00408 return wdtcr; 00409 } 00410 00411 void 00412 wdtcr_construct (WDTCR *wdtcr, uint8_t func_mask) 00413 { 00414 char *name = "WDTCR"; 00415 00416 if (wdtcr == NULL) 00417 avr_error ("passed null ptr"); 00418 00419 vdev_construct ((VDevice *)wdtcr, name, WDTCR_BASE, WDTCR_SIZE, 00420 wdtcr_read, wdtcr_write, wdtcr_reset, wdtcr_reg_name); 00421 00422 wdtcr->func_mask = func_mask; 00423 00424 wdtcr_reset ((VDevice *)wdtcr); 00425 } 00426 00427 void 00428 wdtcr_destroy (void *wdtcr) 00429 { 00430 if (wdtcr == NULL) 00431 return; 00432 00433 vdev_destroy (wdtcr); 00434 } 00435 00436 /* 00437 * Function wdtcr_update: Called when the WDR instruction is issued 00438 */ 00439 void 00440 wdtcr_update (WDTCR *wdtcr) 00441 { 00442 wdtcr->last_WDR = get_program_time (); 00443 } 00444 00445 #if 0 /* This doesn't seem to be used anywhere. */ 00446 static int 00447 wdtcr_get_bit (WDTCR *reg, int bit) 00448 { 00449 return !!(reg->wdtcr & reg->func_mask & (1 << bit)); 00450 } 00451 #endif 00452 00453 static void 00454 wdtcr_set_bit (WDTCR *reg, int bit, int val) 00455 { 00456 reg->wdtcr = set_bit_in_byte (reg->wdtcr, bit, val) & reg->func_mask; 00457 } 00458 00459 static uint8_t 00460 wdtcr_read (VDevice *dev, int addr) 00461 { 00462 WDTCR *reg = (WDTCR *)dev; 00463 00464 return (reg->wdtcr & reg->func_mask); 00465 } 00466 00467 /* 00468 * FIXME: Should the wdtcr->toe_clk counter be reset to TOE_CLKS 00469 * every time a WDTOE is set 1? I.E. does the hw reset the 4 cycle 00470 * counter every time WDTOE is set? This code assumes it does. 00471 */ 00472 static void 00473 wdtcr_write (VDevice *dev, int addr, uint8_t val) 00474 { 00475 WDTCR *reg = (WDTCR *)dev; 00476 uint8_t wd_enabled = (reg->wdtcr & mask_WDE); 00477 00478 CallBack *cb; 00479 00480 if (reg->func_mask & mask_WDTOE) 00481 { /* Device has WDTOE functionality */ 00482 00483 if ((reg->wdtcr & mask_WDE) && !(reg->wdtcr & mask_WDTOE)) 00484 { 00485 /* WDE can _NOT_ be cleared if WDTOE is zero */ 00486 val |= mask_WDE; 00487 } 00488 00489 if (val & mask_WDTOE) 00490 { /* program has set WDTOE */ 00491 reg->toe_clk = TOE_CLKS; 00492 00493 /* create and install the callback if it not already installed */ 00494 if (reg->toe_cb == NULL) 00495 { 00496 cb = callback_new (wdtcr_toe_clr_cb, (AvrClass *)reg); 00497 reg->toe_cb = cb; 00498 avr_core_clk_cb_add ((AvrCore *)vdev_get_core (dev), cb); 00499 } 00500 } 00501 } 00502 00503 reg->wdtcr = (val & reg->func_mask); 00504 00505 if ((wd_enabled == 0) && (val & mask_WDE) && (reg->timer_cb == NULL)) 00506 { 00507 /* install the WD timer callback */ 00508 cb = callback_new (wdtcr_timer_cb, (AvrClass *)reg); 00509 reg->timer_cb = cb; 00510 avr_core_async_cb_add ((AvrCore *)vdev_get_core (dev), cb); 00511 } 00512 00513 if (wd_enabled && ((val & mask_WDE) == 0) && (reg->timer_cb != NULL)) 00514 { 00515 /* tell callback to remove itself */ 00516 reg->timer_cb = NULL; 00517 } 00518 } 00519 00520 static void 00521 wdtcr_reset (VDevice *dev) 00522 { 00523 WDTCR *wdtcr = (WDTCR *)dev; 00524 00525 wdtcr->wdtcr = 0; 00526 00527 wdtcr->last_WDR = get_program_time (); /* FIXME: This might not be the 00528 right thing to do */ 00529 wdtcr->timer_cb = NULL; 00530 00531 wdtcr->toe_clk = TOE_CLKS; 00532 wdtcr->toe_cb = NULL; 00533 } 00534 00535 static char * 00536 wdtcr_reg_name (VDevice *dev, int addr) 00537 { 00538 return vdev_get_name (dev); 00539 } 00540 00541 /* 00542 * Timer callback will remove itself if wdtcr->timer_cb is set NULL. 00543 */ 00544 static int 00545 wdtcr_timer_cb (uint64_t time, AvrClass *data) 00546 { 00547 WDTCR *wdtcr = (WDTCR *)data; 00548 uint64_t time_diff; 00549 uint64_t time_out; 00550 00551 if (wdtcr->timer_cb == NULL) 00552 return CB_RET_REMOVE; 00553 00554 time_diff = time - wdtcr->last_WDR; 00555 time_out = TIMEOUT_BASE * (1 << (wdtcr->wdtcr & mask_WDP)); 00556 00557 if (time_diff > time_out) 00558 { 00559 avr_warning ("watchdog reset: time %lld\n", time_diff); 00560 00561 /* reset the device, we timed out */ 00562 avr_core_irq_raise ((AvrCore *)vdev_get_core ((VDevice *)wdtcr), 00563 irq_vect_table_index (RESET)); 00564 } 00565 00566 return CB_RET_RETAIN; 00567 } 00568 00569 /* 00570 * The WDTOE is cleared by hardware after TOE_CLKS clock cycles. 00571 */ 00572 static int 00573 wdtcr_toe_clr_cb (uint64_t time, AvrClass *data) 00574 { 00575 WDTCR *wdtcr = (WDTCR *)data; 00576 00577 if (wdtcr->toe_cb == NULL) 00578 return CB_RET_REMOVE; 00579 00580 if (wdtcr->toe_clk > 0) 00581 { 00582 wdtcr->toe_clk--; 00583 } 00584 else 00585 { 00586 wdtcr_set_bit (wdtcr, bit_WDTOE, 0); 00587 wdtcr->toe_cb = NULL; /* So we know that cb is not installed */ 00588 return CB_RET_REMOVE; 00589 } 00590 00591 return CB_RET_RETAIN; 00592 } 00593 00594 /****************************************************************************\ 00595 * 00596 * RAMPZ(VDevice) : The RAMPZ register used by ELPM and ESPM instructions. 00597 * 00598 * Even though the rampz register is not available to all devices, we will 00599 * install it for all in the simulator. It just so much easier that way and 00600 * we're already assuming that the compiler generated the correct code in 00601 * many places anyways. Let's see if we get bit. 00602 * 00603 \****************************************************************************/ 00604 00605 static uint8_t rampz_read (VDevice *dev, int addr); 00606 static void rampz_write (VDevice *dev, int addr, uint8_t val); 00607 static void rampz_reset (VDevice *dev); 00608 static char *rampz_reg_name (VDevice *dev, int addr); 00609 00610 RAMPZ * 00611 rampz_new (void) 00612 { 00613 RAMPZ *rampz; 00614 00615 rampz = avr_new (RAMPZ, 1); 00616 rampz_construct (rampz); 00617 class_overload_destroy ((AvrClass *)rampz, rampz_destroy); 00618 00619 return rampz; 00620 } 00621 00622 void 00623 rampz_construct (RAMPZ *rampz) 00624 { 00625 char *name = "RAMPZ"; 00626 00627 if (rampz == NULL) 00628 avr_error ("passed null ptr"); 00629 00630 vdev_construct ((VDevice *)rampz, name, RAMPZ_BASE, RAMPZ_SIZE, 00631 rampz_read, rampz_write, rampz_reset, rampz_reg_name); 00632 00633 rampz->reg = 0; 00634 } 00635 00636 void 00637 rampz_destroy (void *rampz) 00638 { 00639 if (rampz == NULL) 00640 return; 00641 00642 vdev_destroy (rampz); 00643 } 00644 00645 uint8_t 00646 rampz_get (RAMPZ *rampz) 00647 { 00648 return rampz->reg; 00649 } 00650 00651 void 00652 rampz_set (RAMPZ *rampz, uint8_t val) 00653 { 00654 rampz->reg = val; 00655 } 00656 00657 static uint8_t 00658 rampz_read (VDevice *dev, int addr) 00659 { 00660 return rampz_get ((RAMPZ *)dev); 00661 } 00662 00663 static void 00664 rampz_write (VDevice *dev, int addr, uint8_t val) 00665 { 00666 rampz_set ((RAMPZ *)dev, val); 00667 } 00668 00669 static void 00670 rampz_reset (VDevice *dev) 00671 { 00672 display_io_reg (RAMPZ_IO_REG, 0); 00673 ((RAMPZ *)dev)->reg = 0; 00674 } 00675 00676 static char * 00677 rampz_reg_name (VDevice *dev, int addr) 00678 { 00679 return vdev_get_name (dev); 00680 }

Automatically generated by Doxygen 1.3.8 on 11 Aug 2004.