Main Page | File List | Globals | Related Pages

uart.c

Go to the documentation of this file.
00001 /* 00002 * $Id: uart.c,v 1.1 2004/01/02 04:03:21 troth Exp $ 00003 * 00004 **************************************************************************** 00005 * 00006 * simulavr - A simulator for the Atmel AVR family of microcontrollers. 00007 * Copyright (C) 2003 Keith Gudger 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 uart.c 00028 * \brief Module to simulate the AVR's uart module. 00029 */ 00030 00031 #include <config.h> 00032 00033 #include <stdio.h> 00034 #include <stdlib.h> 00035 00036 #include "avrerror.h" 00037 #include "avrmalloc.h" 00038 #include "avrclass.h" 00039 #include "utils.h" 00040 #include "callback.h" 00041 #include "op_names.h" 00042 00043 #include "storage.h" 00044 #include "flash.h" 00045 00046 #include "vdevs.h" 00047 #include "memory.h" 00048 #include "stack.h" 00049 #include "register.h" 00050 #include "sram.h" 00051 #include "eeprom.h" 00052 #include "timers.h" 00053 #include "ports.h" 00054 #include "uart.h" 00055 00056 #include "avrcore.h" 00057 00058 #include "intvects.h" 00059 00060 /****************************************************************************\ 00061 * 00062 * uart Interrupts 00063 * 00064 \****************************************************************************/ 00065 00066 static uint8_t uart_intr_read (VDevice *dev, int addr); 00067 static void uart_intr_write (VDevice *dev, int addr, uint8_t val); 00068 static void uart_intr_reset (VDevice *dev); 00069 static char *uart_intr_reg_name (VDevice *dev, int addr); 00070 static int uart_intr_cb (uint64_t time, AvrClass *data); 00071 00072 int UART_Int_Table[] = { 00073 irq_vect_table_index (UART_RX), /* uart Rx complete */ 00074 irq_vect_table_index (UART_UDRE), /* uart data register empty */ 00075 irq_vect_table_index (UART_TX) /* uart Tx complete */ 00076 }; 00077 00078 int UART0_Int_Table[] = { 00079 irq_vect_table_index (USART0_RX), /* uart Rx complete */ 00080 irq_vect_table_index (USART0_UDRE), /* uart data register empty */ 00081 irq_vect_table_index (USART0_TX) /* uart Tx complete */ 00082 }; 00083 00084 int UART1_Int_Table[] = { 00085 irq_vect_table_index (USART1_RX), /* uart Rx complete */ 00086 irq_vect_table_index (USART1_UDRE), /* uart data register empty */ 00087 irq_vect_table_index (USART1_TX) /* uart Tx complete */ 00088 }; 00089 00090 /** \brief Allocate a new uart interrupt */ 00091 00092 UARTIntr_T * 00093 uart0_intr_new (uint8_t uart_num) 00094 { 00095 UARTIntr_T *uart; 00096 00097 uart = avr_new (UARTIntr_T, 1); 00098 uart0_intr_construct (uart); 00099 class_overload_destroy ((AvrClass *)uart, uart_intr_destroy); 00100 00101 if (uart_num > ONE_UART) 00102 uart->Int_Table = &UART0_Int_Table[0]; 00103 else 00104 uart->Int_Table = &UART_Int_Table[0]; 00105 00106 return uart; 00107 } 00108 00109 UARTIntr_T * 00110 uart1_intr_new (uint8_t uart_num) 00111 { 00112 UARTIntr_T *uart; 00113 00114 uart = avr_new (UARTIntr_T, 1); 00115 uart1_intr_construct (uart, uart_num); 00116 class_overload_destroy ((AvrClass *)uart, uart_intr_destroy); 00117 00118 uart->Int_Table = &UART1_Int_Table[0]; 00119 00120 return uart; 00121 } 00122 00123 /** \brief Constructor for uart interrupt object. */ 00124 00125 void 00126 uart0_intr_construct (UARTIntr_T *uart) 00127 { 00128 char *name = "uartIntr0"; 00129 00130 if (uart == NULL) 00131 avr_error ("passed null ptr"); 00132 00133 vdev_construct ((VDevice *)uart, name, UART_INTR_BASE_0, UART_INTR_SIZE, 00134 uart_intr_read, uart_intr_write, uart_intr_reset, 00135 uart_intr_reg_name); 00136 00137 uart_intr_reset ((VDevice *)uart); 00138 } 00139 00140 void 00141 uart1_intr_construct (UARTIntr_T *uart, uint8_t uart_num) 00142 { 00143 char *name = "uartIntr1"; 00144 00145 if (uart == NULL) 00146 avr_error ("passed null ptr"); 00147 00148 if (uart_num > TWO_UART) 00149 vdev_construct ((VDevice *)uart, name, UART_INTR_BASE_128, 00150 UART_INTR_SIZE, uart_intr_read, uart_intr_write, 00151 uart_intr_reset, uart_intr_reg_name); 00152 else 00153 vdev_construct ((VDevice *)uart, name, UART_INTR_BASE_1, 00154 UART_INTR_SIZE, uart_intr_read, uart_intr_write, 00155 uart_intr_reset, uart_intr_reg_name); 00156 00157 uart_intr_reset ((VDevice *)uart); 00158 } 00159 00160 /** \brief Destructor for uart interrupt object. */ 00161 00162 void 00163 uart_intr_destroy (void *uart) 00164 { 00165 if (uart == NULL) 00166 return; 00167 00168 vdev_destroy (uart); 00169 } 00170 00171 static uint8_t 00172 uart_intr_read (VDevice *dev, int addr) 00173 { 00174 UARTIntr_T *uart = (UARTIntr_T *)dev; 00175 00176 switch (addr - vdev_get_base (dev)) 00177 { 00178 case UART_INTR_UBRR_ADDR: 00179 return (uart->ubrr); 00180 case UART_INTR_UCR_ADDR: 00181 return (uart->ucr); 00182 case UART_INTR_USR_ADDR: 00183 return (uart->usr); 00184 default: 00185 avr_error ("Bad address: 0x%04x", addr); 00186 } 00187 return 0; /* will never get here */ 00188 } 00189 00190 static void 00191 uart_intr_write (VDevice *dev, int addr, uint8_t val) 00192 { 00193 UARTIntr_T *uart = (UARTIntr_T *)dev; 00194 CallBack *cb; 00195 00196 switch (addr - vdev_get_base (dev)) 00197 { 00198 case UART_INTR_UBRR_ADDR: 00199 (uart->ubrr = val); 00200 break; 00201 case UART_INTR_USR_ADDR: 00202 if (val & mask_TXC) 00203 uart->usr &= ~mask_TXC; 00204 break; 00205 case UART_INTR_UCR_ADDR: 00206 (uart->ucr = val); /* look for interrupt enables */ 00207 if (((uart->ucr & mask_TXEN) && (uart->ucr & mask_TXCIE)) 00208 || ((uart->ucr & mask_RXEN) && (uart->ucr & mask_RXCIE)) 00209 || (uart->ucr & mask_UDRIE)) 00210 { 00211 if (uart->intr_cb == NULL) 00212 { 00213 /* we need to install the intr_cb function */ 00214 cb = callback_new (uart_intr_cb, (AvrClass *)uart); 00215 uart->intr_cb = cb; 00216 avr_core_async_cb_add ((AvrCore *)vdev_get_core (dev), 00217 cb); 00218 } 00219 } 00220 else 00221 { 00222 uart->intr_cb = NULL; 00223 /* no interrupt are enabled, remove the callback */ 00224 } 00225 00226 break; 00227 default: 00228 avr_error ("Bad address: 0x%04x", addr); 00229 } 00230 } 00231 00232 static void 00233 uart_intr_reset (VDevice *dev) 00234 { 00235 UARTIntr_T *uart = (UARTIntr_T *)dev; 00236 00237 uart->intr_cb = NULL; 00238 00239 uart->ubrr = 0; 00240 uart->usr = 0; 00241 uart->ucr = 0; 00242 uart->usr_shadow = 0; 00243 } 00244 00245 static char * 00246 uart_intr_reg_name (VDevice *dev, int addr) 00247 { 00248 switch (addr - vdev_get_base (dev)) 00249 { 00250 case UART_INTR_UBRR_ADDR: 00251 return ("UBRR"); 00252 case UART_INTR_UCR_ADDR: 00253 return ("UCR"); 00254 case UART_INTR_USR_ADDR: 00255 return ("USR"); 00256 default: 00257 avr_error ("Bad address: 0x%04x", addr); 00258 } 00259 return NULL; /* will never get here */ 00260 } 00261 00262 static int 00263 uart_intr_cb (uint64_t time, AvrClass *data) 00264 { 00265 UARTIntr_T *uart = (UARTIntr_T *)data; 00266 00267 if (uart->intr_cb == NULL) 00268 return CB_RET_REMOVE; 00269 00270 if ((uart->ucr & mask_RXCIE) && (uart->usr & mask_RXC)) 00271 /* an enabled interrupt occured */ 00272 { 00273 AvrCore *core = (AvrCore *)vdev_get_core ((VDevice *)uart); 00274 avr_core_irq_raise (core, (uart->Int_Table[URX])); 00275 } 00276 00277 if ((uart->ucr & mask_TXCIE) && (uart->usr & mask_TXC)) 00278 /* an enabled interrupt occured */ 00279 { 00280 AvrCore *core = (AvrCore *)vdev_get_core ((VDevice *)uart); 00281 avr_core_irq_raise (core, (uart->Int_Table[UTX])); 00282 uart->usr &= ~mask_TXC; 00283 } 00284 00285 if ((uart->ucr & mask_UDRIE) && (uart->usr & mask_UDRE) 00286 && (uart->usr_shadow & mask_UDRE)) 00287 /* an enabled interrupt occured */ 00288 { 00289 AvrCore *core = (AvrCore *)vdev_get_core ((VDevice *)uart); 00290 avr_core_irq_raise (core, (uart->Int_Table[UUDRE])); 00291 uart->usr_shadow &= ~mask_UDRE; /* only issue one interrupt / udre */ 00292 } 00293 00294 return CB_RET_RETAIN; 00295 } 00296 00297 /****************************************************************************\ 00298 * 00299 * uart 00300 * 00301 \****************************************************************************/ 00302 00303 static uint8_t uart_read (VDevice *dev, int addr); 00304 static void uart_write (VDevice *dev, int addr, uint8_t val); 00305 static void uart_reset (VDevice *dev); 00306 static char *uart_reg_name (VDevice *dev, int addr); 00307 static int uart_clk_incr_cb (uint64_t ck, AvrClass *data); 00308 00309 /** \brief Allocate a new uart structure. */ 00310 00311 UART_T * 00312 uart_new (uint8_t uart_num) 00313 { 00314 UART_T *uart; 00315 00316 uart = avr_new (UART_T, 1); 00317 if (uart_num > ONE_UART) 00318 uart1_construct (uart, uart_num); 00319 else 00320 uart0_construct (uart); 00321 class_overload_destroy ((AvrClass *)uart, uart_destroy); 00322 00323 return uart; 00324 } 00325 00326 /** \brief Constructor for uart object. */ 00327 00328 void 00329 uart0_construct (UART_T *uart) 00330 { 00331 char *name = "uart0"; 00332 00333 if (uart == NULL) 00334 avr_error ("passed null ptr"); 00335 00336 vdev_construct ((VDevice *)uart, name, UART_BASE_0, UART_SIZE, uart_read, 00337 uart_write, uart_reset, uart_reg_name); 00338 00339 uart_reset ((VDevice *)uart); 00340 uart->int_name = "uartIntr0"; 00341 } 00342 00343 void 00344 uart1_construct (UART_T *uart, uint8_t uart_num) 00345 { 00346 char *name = "uart1"; 00347 00348 if (uart == NULL) 00349 avr_error ("passed null ptr"); 00350 00351 if (uart_num > TWO_UART) 00352 vdev_construct ((VDevice *)uart, name, UART_BASE_128, UART_SIZE, 00353 uart_read, uart_write, uart_reset, uart_reg_name); 00354 else 00355 vdev_construct ((VDevice *)uart, name, UART_BASE_1, UART_SIZE, 00356 uart_read, uart_write, uart_reset, uart_reg_name); 00357 00358 uart_reset ((VDevice *)uart); 00359 uart->int_name = "uartIntr1"; 00360 } 00361 00362 /** \brief Destructor for uart object. */ 00363 00364 void 00365 uart_destroy (void *uart) 00366 { 00367 if (uart == NULL) 00368 return; 00369 00370 vdev_destroy (uart); 00371 } 00372 00373 static uint8_t 00374 uart_read (VDevice *dev, int addr) 00375 { 00376 UART_T *uart = (UART_T *)dev; 00377 UARTIntr_T *uart_t; 00378 int offset = addr - vdev_get_base (dev); 00379 uint16_t udr_temp; 00380 00381 uart_t = 00382 (UARTIntr_T *)avr_core_get_vdev_by_name ((AvrCore *) 00383 vdev_get_core ((VDevice *) 00384 uart), 00385 uart->int_name); 00386 00387 if (offset == UART_UDR_ADDR) 00388 { 00389 uart_t->usr &= ~mask_RXC; /* clear RXC bit in USR */ 00390 if (uart->clk_cb) /* call back already installed */ 00391 { 00392 udr_temp = uart_port_rd (addr); 00393 uart->udr_rx = (uint8_t) udr_temp; /* lower 8 bits */ 00394 if ((uart_t->ucr & mask_CHR9) && /* 9 bits rec'd */ 00395 (udr_temp & (1 << 8))) /* hi bit set */ 00396 uart_t->ucr |= mask_RXB8; 00397 else 00398 uart_t->ucr &= ~mask_RXB8; 00399 } 00400 return uart->udr_rx; 00401 } 00402 else 00403 avr_error ("Bad address: 0x%04x", addr); 00404 00405 return 0; /* will never get here */ 00406 } 00407 00408 static void 00409 uart_write (VDevice *dev, int addr, uint8_t val) 00410 { 00411 UART_T *uart = (UART_T *)dev; 00412 UARTIntr_T *uart_t; 00413 int offset = addr - vdev_get_base (dev); 00414 CallBack *cb; 00415 00416 uart_t = 00417 (UARTIntr_T *)avr_core_get_vdev_by_name ((AvrCore *) 00418 vdev_get_core ((VDevice *) 00419 uart), 00420 uart->int_name); 00421 00422 if (offset == UART_UDR_ADDR) 00423 { 00424 if (uart_t->usr & mask_UDRE) 00425 { 00426 uart_t->usr &= ~mask_UDRE; 00427 uart_t->usr_shadow &= ~mask_UDRE; 00428 } 00429 else 00430 { 00431 uart_t->usr |= mask_UDRE; 00432 uart_t->usr_shadow |= mask_UDRE; 00433 } 00434 uart->udr_tx = val; 00435 00436 /* 00437 * When the user writes to UDR, a callback is installed for 00438 * clock generated increments. 00439 */ 00440 00441 uart->divisor = (uart_t->ubrr + 1) * 16; 00442 00443 /* install the clock incrementor callback (with flair!) */ 00444 00445 if (uart->clk_cb == NULL) 00446 { 00447 cb = callback_new (uart_clk_incr_cb, (AvrClass *)uart); 00448 uart->clk_cb = cb; 00449 avr_core_clk_cb_add ((AvrCore *)vdev_get_core ((VDevice *)uart), 00450 cb); 00451 } 00452 00453 /* set up timer for 8 or 9 clocks based on ucr 00454 (includes start and stop bits) */ 00455 00456 uart->tcnt = (uart_t->ucr & mask_CHR9) ? 11 : 10; 00457 } 00458 else 00459 { 00460 avr_error ("Bad address: 0x%04x", addr); 00461 } 00462 } 00463 00464 static void 00465 uart_reset (VDevice *dev) 00466 { 00467 UART_T *uart = (UART_T *)dev; 00468 00469 uart->clk_cb = NULL; 00470 00471 uart->udr_rx = 0; 00472 uart->udr_tx = 0; 00473 uart->tcnt = 0; 00474 uart->divisor = 0; 00475 } 00476 00477 static char * 00478 uart_reg_name (VDevice *dev, int addr) 00479 { 00480 switch (addr - vdev_get_base (dev)) 00481 { 00482 case UART_UDR_ADDR: 00483 return "UDR"; 00484 default: 00485 avr_error ("Bad address: 0x%04x", addr); 00486 } 00487 00488 return NULL; 00489 } 00490 00491 static int 00492 uart_clk_incr_cb (uint64_t ck, AvrClass *data) 00493 { 00494 UART_T *uart = (UART_T *)data; 00495 UARTIntr_T *uart_t; 00496 uint8_t last = uart->tcnt; 00497 00498 uart_t = 00499 (UARTIntr_T *)avr_core_get_vdev_by_name ((AvrCore *) 00500 vdev_get_core ((VDevice *) 00501 uart), 00502 uart->int_name); 00503 00504 if (uart->clk_cb == NULL) 00505 return CB_RET_REMOVE; 00506 00507 if (uart->divisor <= 0) 00508 avr_error ("Bad divisor value: %d", uart->divisor); 00509 00510 /* decrement clock if ck is a mutliple of divisor */ 00511 00512 uart->tcnt -= ((ck % uart->divisor) == 0); 00513 00514 if (uart->tcnt != last) /* we've changed the counter */ 00515 { 00516 if (uart->tcnt == 0) 00517 { 00518 if (uart_t->usr & mask_UDRE) /* data register empty */ 00519 { 00520 uart_t->usr |= mask_TXC; 00521 return CB_RET_REMOVE; 00522 } 00523 else /* there's a byte waiting to go */ 00524 { 00525 uart_t->usr |= mask_UDRE; 00526 uart_t->usr_shadow |= mask_UDRE; /* also write shadow */ 00527 00528 /* set up timer for 8 or 9 clocks based on ucr, 00529 (includes start and stop bits) */ 00530 00531 uart->tcnt = (uart_t->ucr & mask_CHR9) ? 11 : 10; 00532 } 00533 } 00534 } 00535 00536 return CB_RET_RETAIN; 00537 } 00538 00539 uint16_t 00540 uart_port_rd (int addr) 00541 { 00542 int data; 00543 char line[80]; 00544 00545 while (1) 00546 { 00547 fprintf (stderr, "\nEnter 9 bits of hex data to read into the uart at " 00548 "address 0x%04x: ", addr); 00549 00550 /* try to read in a line of input */ 00551 if (fgets (line, sizeof (line), stdin) == NULL) 00552 continue; 00553 00554 /* try to parse the line for a byte of data */ 00555 if (sscanf (line, "%x\n", &data) != 1) 00556 continue; 00557 00558 break; 00559 } 00560 00561 return (uint16_t) (data & 0x1ff); 00562 } 00563 00564 void 00565 uart_port_wr (uint8_t val) 00566 { 00567 fprintf (stderr, "wrote 0x%02x to uart\n", val); 00568 }

Automatically generated by Doxygen 1.3.8 on 11 Aug 2004.