38 #include "avrmalloc.h"
67 static void uart_iadd_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
69 static uint8_t uart_intr_read (VDevice *dev,
int addr);
70 static void uart_intr_write (VDevice *dev,
int addr, uint8_t val);
71 static void uart_intr_reset (VDevice *dev);
72 static int uart_intr_cb (uint64_t time, AvrClass *data);
74 unsigned int UART_Int_Table[] = {
75 irq_vect_table_index (UART_RX),
76 irq_vect_table_index (UART_UDRE),
77 irq_vect_table_index (UART_TX)
80 unsigned int UART0_Int_Table[] = {
81 irq_vect_table_index (USART0_RX),
82 irq_vect_table_index (USART0_UDRE),
83 irq_vect_table_index (USART0_TX)
86 unsigned int UART1_Int_Table[] = {
87 irq_vect_table_index (USART1_RX),
88 irq_vect_table_index (USART1_UDRE),
89 irq_vect_table_index (USART1_TX)
98 return (VDevice *)uart_intr_new (addr, name, data);
100 avr_error (
"Attempted UART create with NULL data pointer");
105 uart_intr_new (
int addr,
char *name,
void *data)
107 uint8_t *uart_num = (uint8_t *) data;
110 uart =
avr_new (UARTIntr_T, 1);
114 if (*uart_num == USART0)
115 uart->Int_Table = &UART0_Int_Table[0];
116 else if (*uart_num == USART1)
117 uart->Int_Table = &UART1_Int_Table[0];
119 uart->Int_Table = &UART_Int_Table[0];
121 uart_iadd_addr ((VDevice *)uart, addr, name, 0, NULL);
134 uart_intr_reset, uart_iadd_addr);
136 uart_intr_reset ((VDevice *)uart);
140 uart_iadd_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
void *data)
142 UARTIntr_T *uart = (UARTIntr_T *)vdev;
144 if (strncmp (
"UBRRH", name, 5) == 0)
146 uart->ubrrh_addr = addr;
149 else if ((strncmp (
"UBRR", name, 4) == 0)
150 || (strncmp (
"UBRR0", name, 5) == 0)
151 || (strncmp (
"UBRR1", name, 5) == 0))
153 uart->ubrrl_addr = addr;
156 else if ((strncmp (
"USR", name, 3) == 0)
157 || (strncmp (
"UCSR0A", name, 6) == 0)
158 || (strncmp (
"UCSR1A", name, 6) == 0))
160 uart->usr_addr = addr;
163 else if ((strncmp (
"UCR", name, 3) == 0)
164 || (strncmp (
"UCSR0B", name, 6) == 0)
165 || (strncmp (
"UCSR1B", name, 6) == 0))
167 uart->ucr_addr = addr;
172 avr_error (
"invalid UART register name: '%s' @ 0x%04x", name, addr);
188 uart_intr_read (VDevice *dev,
int addr)
190 UARTIntr_T *uart = (UARTIntr_T *)dev;
192 if (addr == uart->ubrrl_addr)
194 return (uart->ubrr & 0xff);
197 else if (addr == uart->ubrrh_addr)
199 return (uart->ubrr >> 8);
202 else if (addr == uart->ucr_addr)
207 else if (addr == uart->usr_addr)
221 uart_intr_write (VDevice *dev,
int addr, uint8_t val)
223 UARTIntr_T *uart = (UARTIntr_T *)dev;
226 if (addr == uart->ubrrl_addr)
228 uart->ubrr = val + (uart->ubrr_temp << 8);
231 else if (addr == uart->ubrrh_addr)
233 uart->ubrr_temp = val;
236 else if (addr == uart->usr)
239 uart->usr &= ~mask_TXC;
242 else if (addr == uart->ucr_addr)
246 if (((uart->ucr & mask_TXEN) && (uart->ucr & mask_TXCIE))
247 || ((uart->ucr & mask_RXEN) && (uart->ucr & mask_RXCIE))
248 || (uart->ucr & mask_UDRIE))
250 if (uart->intr_cb == NULL)
253 cb = callback_new (uart_intr_cb, (AvrClass *)uart);
260 uart->intr_cb = NULL;
272 uart_intr_reset (VDevice *dev)
274 UARTIntr_T *uart = (UARTIntr_T *)dev;
276 uart->intr_cb = NULL;
281 uart->usr_shadow = 0;
285 uart_intr_cb (uint64_t time, AvrClass *data)
287 UARTIntr_T *uart = (UARTIntr_T *)data;
289 if (uart->intr_cb == NULL)
290 return CB_RET_REMOVE;
292 if ((uart->ucr & mask_RXCIE) && (uart->usr & mask_RXC))
299 if ((uart->ucr & mask_TXCIE) && (uart->usr & mask_TXC))
304 uart->usr &= ~mask_TXC;
307 if ((uart->ucr & mask_UDRIE) && (uart->usr & mask_UDRE)
308 && (uart->usr_shadow & mask_UDRE))
313 uart->usr_shadow &= ~mask_UDRE;
316 return CB_RET_RETAIN;
325 static void uart_add_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
327 static uint8_t uart_read (VDevice *dev,
int addr);
328 static void uart_write (VDevice *dev,
int addr, uint8_t val);
329 static void uart_reset (VDevice *dev);
330 static int uart_clk_incr_cb (uint64_t ck, AvrClass *data);
337 return (VDevice *)uart_new (addr, name, rel_addr);
341 uart_new (
int addr,
char *name,
int rel_addr)
361 vdev_construct ((VDevice *)uart, uart_read, uart_write, uart_reset,
364 uart_add_addr ((VDevice *)uart, addr, name, 0, NULL);
366 uart->related_addr = rel_addr;
367 uart_reset ((VDevice *)uart);
371 uart_add_addr (VDevice *vdev,
int addr,
char *name,
int ref_addr,
void *data)
373 UART_T *uart = (UART_T *)vdev;
375 if (strncmp (
"UDR", name, 3) == 0)
377 uart->udr_addr = addr;
382 avr_error (
"invalid SPI register name: '%s' @ 0x%04x", name, addr);
398 uart_read (VDevice *dev,
int addr)
400 UART_T *uart = (UART_T *)dev;
410 if (addr == uart->udr_addr)
412 uart_t->usr &= ~mask_RXC;
415 udr_temp = uart_port_rd (addr);
416 uart->udr_rx = (uint8_t) udr_temp;
417 if ((uart_t->ucr & mask_CHR9) &&
418 (udr_temp & (1 << 8)))
419 uart_t->ucr |= mask_RXB8;
421 uart_t->ucr &= ~mask_RXB8;
435 uart_write (VDevice *dev,
int addr, uint8_t val)
437 UART_T *uart = (UART_T *)dev;
447 if (addr == uart->udr_addr)
449 if (uart_t->usr & mask_UDRE)
451 uart_t->usr &= ~mask_UDRE;
452 uart_t->usr_shadow &= ~mask_UDRE;
456 uart_t->usr |= mask_UDRE;
457 uart_t->usr_shadow |= mask_UDRE;
466 uart->divisor = (uart_t->ubrr + 1) * 16;
470 if (uart->clk_cb == NULL)
472 cb = callback_new (uart_clk_incr_cb, (AvrClass *)uart);
481 uart->tcnt = (uart_t->ucr & mask_CHR9) ? 11 : 10;
491 uart_reset (VDevice *dev)
493 UART_T *uart = (UART_T *)dev;
504 uart_clk_incr_cb (uint64_t ck, AvrClass *data)
506 UART_T *uart = (UART_T *)data;
508 uint8_t last = uart->tcnt;
516 if (uart->clk_cb == NULL)
517 return CB_RET_REMOVE;
519 if (uart->divisor <= 0)
520 avr_error (
"Bad divisor value: %d", uart->divisor);
524 uart->tcnt -= ((ck % uart->divisor) == 0);
526 if (uart->tcnt != last)
530 if (uart_t->usr & mask_UDRE)
532 uart_t->usr |= mask_TXC;
534 return CB_RET_REMOVE;
538 uart_t->usr |= mask_UDRE;
539 uart_t->usr_shadow |= mask_UDRE;
544 uart->tcnt = (uart_t->ucr & mask_CHR9) ? 11 : 10;
549 return CB_RET_RETAIN;
553 uart_port_rd (
int addr)
561 "\nEnter 9 bits of hex data to read into the uart at "
562 "address 0x%04x: ", addr);
565 if (fgets (line,
sizeof (line), stdin) == NULL)
569 if (sscanf (line,
"%x\n", &data) != 1)
575 return (uint16_t) (data & 0x1ff);
579 uart_port_wr (uint8_t val)
581 fprintf (stderr,
"wrote 0x%02x to uart\n", val);