Main Page | File List | Globals | Related Pages

ports.c

Go to the documentation of this file.
00001 /* 00002 * $Id: ports.c,v 1.15 2003/12/01 09:10:15 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 /** 00027 * \file ports.c 00028 * \brief Module for accessing simulated I/O ports. 00029 * 00030 * Defines an abstract Port class as well as subclasses for each individual 00031 * port. 00032 */ 00033 00034 #include <config.h> 00035 00036 #include <stdio.h> 00037 #include <stdlib.h> 00038 00039 #include "avrerror.h" 00040 #include "avrmalloc.h" 00041 #include "avrclass.h" 00042 #include "utils.h" 00043 #include "callback.h" 00044 #include "op_names.h" 00045 00046 #include "storage.h" 00047 #include "flash.h" 00048 00049 #include "vdevs.h" 00050 #include "memory.h" 00051 #include "stack.h" 00052 #include "register.h" 00053 #include "sram.h" 00054 #include "eeprom.h" 00055 #include "timers.h" 00056 #include "ports.h" 00057 00058 #include "avrcore.h" 00059 00060 /****************************************************************************\ 00061 * 00062 * global variables 00063 * 00064 \****************************************************************************/ 00065 00066 /** \brief FIXME: This should be static. */ 00067 char *name_PIN[] = { "PINA", "PINB", "PINC", "PIND", "PINE", "PINF" }; 00068 00069 /** \brief FIXME: This should be static. */ 00070 char *name_DDR[] = { "DDRA", "DDRB", "DDRC", "DDRD", "DDRE", "DDRF" }; 00071 00072 /** \brief FIXME: This should be static. */ 00073 char *name_PORT[] = { "PORTA", "PORTB", "PORTC", "PORTD", "PORTE", "PORTF" }; 00074 00075 /****************************************************************************\ 00076 * 00077 * Local static prototypes. 00078 * 00079 \****************************************************************************/ 00080 00081 static uint8_t port_reg_read (VDevice *dev, int addr); 00082 static void port_reg_write (VDevice *dev, int addr, uint8_t val); 00083 static void port_reset (VDevice *dev); 00084 static char *port_reg_name (VDevice *dev, int addr); 00085 00086 static uint8_t port_read_pin (Port *p, int addr); 00087 00088 static uint8_t port_read_port (Port *p, int addr); 00089 static void port_write_port (Port *p, int addr, uint8_t val); 00090 00091 static uint8_t port_read_ddr (Port *p, int addr); 00092 static void port_write_ddr (Port *p, int addr, uint8_t val); 00093 00094 /****************************************************************************\ 00095 * 00096 * Port(VDevice) : I/O Port registers 00097 * 00098 \****************************************************************************/ 00099 00100 /** 00101 * \brief Allocates a new Port object. 00102 * 00103 * This is a virtual method for higher level port implementations and as such 00104 * should not be used directly. 00105 */ 00106 Port * 00107 port_new (char *name, int base, int pins, PortFP_AltRd alt_rd, 00108 PortFP_AltWr alt_wr) 00109 { 00110 Port *p; 00111 00112 p = avr_new (Port, 1); 00113 port_construct (p, name, base, pins, alt_rd, alt_wr); 00114 class_overload_destroy ((AvrClass *)p, port_destroy); 00115 00116 return p; 00117 } 00118 00119 /** 00120 * \brief Constructor for the Port object. 00121 * 00122 * This is a virtual method for higher level port implementations and as such 00123 * should not be used directly. 00124 */ 00125 void 00126 port_construct (Port *p, char *name, int base, int pins, PortFP_AltRd alt_rd, 00127 PortFP_AltWr alt_wr) 00128 { 00129 if (p == NULL) 00130 avr_error ("passed null ptr"); 00131 00132 vdev_construct ((VDevice *)p, name, base, PORT_SIZE, port_reg_read, 00133 port_reg_write, port_reset, port_reg_name); 00134 00135 p->mask = (uint8_t) (((uint16_t) 1 << pins) - 1); 00136 00137 p->alt_rd = alt_rd; 00138 p->alt_wr = alt_wr; 00139 00140 p->ext_rd = NULL; 00141 p->ext_wr = NULL; 00142 00143 port_reset ((VDevice *)p); 00144 } 00145 00146 static void 00147 port_reset (VDevice *dev) 00148 { 00149 Port *p = (Port *)dev; 00150 00151 p->port = 0; 00152 p->ddr = 0; 00153 00154 p->ext_enable = 1; 00155 } 00156 00157 /** 00158 * \brief Destructor for the Port object 00159 * 00160 * This is a virtual method for higher level port implementations and as such 00161 * should not be used directly. 00162 */ 00163 void 00164 port_destroy (void *p) 00165 { 00166 if (p == NULL) 00167 return; 00168 00169 vdev_destroy (p); 00170 } 00171 00172 /** \brief Disable external port functionality. 00173 * 00174 * This is only used when dumping memory to core file. See mem_io_fetch(). 00175 */ 00176 void 00177 port_ext_disable (Port *p) 00178 { 00179 p->ext_enable = 0; 00180 } 00181 00182 /** \brief Enable external port functionality. 00183 * 00184 * This is only used when dumping memory to core file. See mem_io_fetch(). 00185 */ 00186 void 00187 port_ext_enable (Port *p) 00188 { 00189 p->ext_enable = 1; 00190 } 00191 00192 /** 00193 * \brief Attaches read and write functions to a particular port 00194 * 00195 * I think I may have this backwards. Having the virtual hardware supply 00196 * functions for the core to call on every io read/write, might cause missed 00197 * events (like edge triggered). I'm really not too sure how to handle this. 00198 * 00199 * In the future, it might be better to have the core supply a function for 00200 * the virtual hardware to call when data is written to the device. The device 00201 * supplied function could then check if an interrupt should be generated or 00202 * just simply write to the port data register. 00203 * 00204 * For now, leave it as is since it's easier to test if you can block when the 00205 * device is reading from the virtual hardware. 00206 */ 00207 void 00208 port_add_ext_rd_wr (Port *p, PortFP_ExtRd ext_rd, PortFP_ExtWr ext_wr) 00209 { 00210 p->ext_rd = ext_rd; 00211 p->ext_wr = ext_wr; 00212 } 00213 00214 static uint8_t 00215 port_read_pin (Port *p, int addr) 00216 { 00217 uint8_t data; 00218 00219 /* get the data from the external virtual hardware if connected */ 00220 if (p->ext_rd && p->ext_enable) 00221 data = p->ext_rd (addr) & p->mask; 00222 else 00223 data = 0; 00224 00225 /* 00226 * For a pin n to be enabled as input, DDRn == 0, 00227 * otherwise it will always read 0. 00228 */ 00229 data &= ~(p->ddr); 00230 00231 /* 00232 * Pass data to alternate read so as to check alternate functions of 00233 * pins for that port. 00234 */ 00235 /* if (p->alt_rd) */ 00236 /* data = p->alt_rd(p, addr, data); */ 00237 00238 return data; 00239 } 00240 00241 static uint8_t 00242 port_read_port (Port *p, int addr) 00243 { 00244 return (p->port & p->mask); 00245 } 00246 00247 static void 00248 port_write_port (Port *p, int addr, uint8_t val) 00249 { 00250 /* update port register */ 00251 p->port = (val & p->mask); 00252 00253 /* 00254 * Since changing p->port might change what the virtual hardware 00255 * sees, we need to call ext_wr() to pass change allong. 00256 */ 00257 if (p->ext_wr && p->ext_enable) 00258 p->ext_wr (addr, (p->port & p->ddr)); 00259 } 00260 00261 static uint8_t 00262 port_read_ddr (Port *p, int addr) 00263 { 00264 return (p->ddr & p->mask); 00265 } 00266 00267 static void 00268 port_write_ddr (Port *p, int addr, uint8_t val) 00269 { 00270 /* update ddr register */ 00271 p->ddr = (val & p->mask); 00272 00273 /* 00274 * Since changing p->ddr might change what the virtual hardware 00275 * sees, we need to call ext_wr() to pass change allong. 00276 */ 00277 if (p->ext_wr && p->ext_enable) 00278 p->ext_wr (addr, (p->port & p->ddr)); 00279 } 00280 00281 static uint8_t 00282 port_reg_read (VDevice *dev, int addr) 00283 { 00284 Port *p = (Port *)dev; 00285 uint8_t val = 0; 00286 00287 switch (addr - vdev_get_base (dev)) 00288 { 00289 case PORT_DDR: 00290 val = port_read_ddr ((Port *)p, addr); 00291 break; 00292 case PORT_PIN: 00293 val = port_read_pin ((Port *)p, addr); 00294 break; 00295 case PORT_PORT: 00296 val = port_read_port ((Port *)p, addr); 00297 break; 00298 00299 default: 00300 avr_error ("Invalid Port Address: 0x%02x", addr); 00301 } 00302 00303 return val; 00304 } 00305 00306 static void 00307 port_reg_write (VDevice *dev, int addr, uint8_t val) 00308 { 00309 Port *p = (Port *)dev; 00310 00311 switch (addr - vdev_get_base (dev)) 00312 { 00313 case PORT_PIN: 00314 avr_error ("Attempt to write to readonly PINx register"); 00315 00316 case PORT_DDR: 00317 port_write_ddr ((Port *)p, addr, val); 00318 return; 00319 00320 case PORT_PORT: 00321 port_write_port ((Port *)p, addr, val); 00322 return; 00323 } 00324 avr_error ("Invalid Port Address: 0x%02x", addr); 00325 } 00326 00327 static char * 00328 port_reg_name (VDevice *dev, int addr) 00329 { 00330 int port = vdev_get_name (dev)[4] - 'A'; 00331 00332 switch (addr - vdev_get_base (dev)) 00333 { 00334 case PORT_PIN: 00335 return name_PIN[port]; 00336 case PORT_DDR: 00337 return name_DDR[port]; 00338 case PORT_PORT: 00339 return name_PORT[port]; 00340 } 00341 avr_error ("Invalid Port %c Address: 0x%02x", addr, 'A' + port); 00342 return NULL; 00343 } 00344 00345 /****************************************************************************\ 00346 * 00347 * PortA(Port) : Port A Definition. 00348 * 00349 \****************************************************************************/ 00350 00351 /** \brief Allocate a new PortA object. */ 00352 00353 PortA * 00354 porta_new (int pins) 00355 { 00356 PortA *p; 00357 00358 p = avr_new (PortA, 1); 00359 porta_construct (p, pins); 00360 class_overload_destroy ((AvrClass *)p, porta_destroy); 00361 00362 return p; 00363 } 00364 00365 /** 00366 * \brief Constructor for the PortA object. 00367 * 00368 * Port A also functions as low byte of address into external SRAM if enabled. 00369 * - PAn <--> ADn 00370 */ 00371 void 00372 porta_construct (PortA *p, int pins) 00373 { 00374 if (p == NULL) 00375 avr_error ("passed null ptr"); 00376 00377 port_construct ((Port *)p, name_PORT[PORT_A], PORT_A_BASE, pins, NULL, 00378 NULL); 00379 } 00380 00381 /** \brief Destructor for the PortA object. */ 00382 00383 void 00384 porta_destroy (void *p) 00385 { 00386 if (p == NULL) 00387 return; 00388 00389 port_destroy (p); 00390 } 00391 00392 /****************************************************************************\ 00393 * 00394 * PortB(Port) : Port B Definition. 00395 * 00396 \****************************************************************************/ 00397 00398 /** \brief Allocate a new PortB object. */ 00399 00400 PortB * 00401 portb_new (int pins) 00402 { 00403 PortB *p; 00404 00405 p = avr_new (PortB, 1); 00406 portb_construct (p, pins); 00407 class_overload_destroy ((AvrClass *)p, portb_destroy); 00408 00409 return p; 00410 } 00411 00412 /** \brief Constructor for the PortB object. */ 00413 00414 void 00415 portb_construct (PortB *p, int pins) 00416 { 00417 if (p == NULL) 00418 avr_error ("passed null ptr"); 00419 00420 port_construct ((Port *)p, name_PORT[PORT_B], PORT_B_BASE, pins, NULL, 00421 NULL); 00422 } 00423 00424 /** \brief Destructor for the PortB object. */ 00425 00426 void 00427 portb_destroy (void *p) 00428 { 00429 if (p == NULL) 00430 return; 00431 00432 port_destroy (p); 00433 } 00434 00435 /****************************************************************************\ 00436 * 00437 * PortC(Port) : Port C Definition. 00438 * 00439 \****************************************************************************/ 00440 00441 /** \brief Allocate a new PortC object. */ 00442 00443 PortC * 00444 portc_new (int pins) 00445 { 00446 PortC *p; 00447 00448 p = avr_new (PortC, 1); 00449 portc_construct (p, pins); 00450 class_overload_destroy ((AvrClass *)p, portc_destroy); 00451 00452 return p; 00453 } 00454 00455 /** \brief Constructor for the PortC object. */ 00456 00457 void 00458 portc_construct (PortC *p, int pins) 00459 { 00460 if (p == NULL) 00461 avr_error ("passed null ptr"); 00462 00463 port_construct ((Port *)p, name_PORT[PORT_C], PORT_C_BASE, pins, NULL, 00464 NULL); 00465 } 00466 00467 /** \brief Destructor for the PortC object. */ 00468 00469 void 00470 portc_destroy (void *p) 00471 { 00472 if (p == NULL) 00473 return; 00474 00475 port_destroy (p); 00476 } 00477 00478 /****************************************************************************\ 00479 * 00480 * PortD(Port) : Port D Definition. 00481 * 00482 \****************************************************************************/ 00483 00484 /** \brief Allocate a new PortD object. */ 00485 00486 PortD * 00487 portd_new (int pins) 00488 { 00489 PortD *p; 00490 00491 p = avr_new (PortD, 1); 00492 portd_construct (p, pins); 00493 class_overload_destroy ((AvrClass *)p, portd_destroy); 00494 00495 return p; 00496 } 00497 00498 /** \brief Constructor for the PortD object. */ 00499 00500 void 00501 portd_construct (PortD *p, int pins) 00502 { 00503 if (p == NULL) 00504 avr_error ("passed null ptr"); 00505 00506 port_construct ((Port *)p, name_PORT[PORT_D], PORT_D_BASE, pins, NULL, 00507 NULL); 00508 } 00509 00510 /** \brief Destructor for the PortD object. */ 00511 00512 void 00513 portd_destroy (void *p) 00514 { 00515 if (p == NULL) 00516 return; 00517 00518 port_destroy (p); 00519 } 00520 00521 /****************************************************************************\ 00522 * 00523 * PortE(Port) : Port E Definition. 00524 * 00525 \****************************************************************************/ 00526 00527 /** \brief Allocate a new PortE object. */ 00528 00529 PortE * 00530 porte_new (int pins) 00531 { 00532 PortE *p; 00533 00534 p = avr_new (PortE, 1); 00535 porte_construct (p, pins); 00536 class_overload_destroy ((AvrClass *)p, porte_destroy); 00537 00538 return p; 00539 } 00540 00541 /** \brief Constructor for the PortE object. */ 00542 00543 void 00544 porte_construct (PortE *p, int pins) 00545 { 00546 if (p == NULL) 00547 avr_error ("passed null ptr"); 00548 00549 port_construct ((Port *)p, name_PORT[PORT_E], PORT_E_BASE, pins, NULL, 00550 NULL); 00551 } 00552 00553 /** \brief Destructor for the PortE object. */ 00554 00555 void 00556 porte_destroy (void *p) 00557 { 00558 if (p == NULL) 00559 return; 00560 00561 port_destroy (p); 00562 } 00563 00564 /****************************************************************************\ 00565 * 00566 * PortF(Port) : Port F Definition. 00567 * 00568 \****************************************************************************/ 00569 00570 /** \brief Allocate a new PortF object. */ 00571 00572 PortF * 00573 portf_new (int pins) 00574 { 00575 PortF *p; 00576 00577 p = avr_new (PortF, 1); 00578 portf_construct (p, pins); 00579 class_overload_destroy ((AvrClass *)p, portf_destroy); 00580 00581 return p; 00582 } 00583 00584 /** \brief Constructor for the PortF object. */ 00585 00586 void 00587 portf_construct (PortF *p, int pins) 00588 { 00589 if (p == NULL) 00590 avr_error ("passed null ptr"); 00591 00592 port_construct ((Port *)p, name_PORT[PORT_F], PORT_F_BASE, pins, NULL, 00593 NULL); 00594 } 00595 00596 /** \brief Destructor for the PortF object. */ 00597 00598 void 00599 portf_destroy (void *p) 00600 { 00601 if (p == NULL) 00602 return; 00603 00604 port_destroy (p); 00605 }

Automatically generated by Doxygen 1.3.8 on 11 Aug 2004.