From b77d26e251cf8647a835b193c04b86ca8e4e3aa1 Mon Sep 17 00:00:00 2001 From: hovercraft-github Date: Wed, 15 Feb 2017 17:28:51 +0800 Subject: [PATCH] UART: separate TX/RX pumps, sticky UDRC and RXC interrupt flags. Fixes #104, #193 and others. --- simavr/cores/sim_90usb162.c | 31 +--- simavr/cores/sim_mega128.c | 66 +------- simavr/cores/sim_mega1280.c | 128 +------------- simavr/cores/sim_mega1281.c | 66 +------- simavr/cores/sim_mega128rfa1.c | 65 +------ simavr/cores/sim_mega128rfr2.c | 65 +------ simavr/cores/sim_mega169.c | 32 +--- simavr/cores/sim_mega2560.c | 128 +------------- simavr/cores/sim_megax.h | 35 +--- simavr/cores/sim_megax4.h | 67 +------- simavr/cores/sim_megax8.h | 35 +--- simavr/cores/sim_tiny2313.c | 36 +--- simavr/sim/avr_lin.c | 13 +- simavr/sim/avr_uart.c | 301 +++++++++++++++++++++++++-------- simavr/sim/avr_uart.h | 100 ++++++++++- 15 files changed, 379 insertions(+), 789 deletions(-) diff --git a/simavr/cores/sim_90usb162.c b/simavr/cores/sim_90usb162.c index bfc05d4..bd3f136 100644 --- a/simavr/cores/sim_90usb162.c +++ b/simavr/cores/sim_90usb162.c @@ -91,37 +91,8 @@ const struct mcu_t { }, AVR_IOPORT_DECLARE(d, 'D', D), - .uart1 = { - .disabled = AVR_IO_REGBIT(PRR1,PRUSART1), - .name = '1', - .r_udr = UDR1, - - .txen = AVR_IO_REGBIT(UCSR1B, TXEN1), - .rxen = AVR_IO_REGBIT(UCSR1B, RXEN1), - .ucsz = AVR_IO_REGBITS(UCSR1C, UCSZ10, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR1B, UCSZ12), // 1 bits + AVR_UARTX_DECLARE(1, PRR1, PRUSART1), - .r_ucsra = UCSR1A, - .r_ucsrb = UCSR1B, - .r_ucsrc = UCSR1C, - .r_ubrrl = UBRR1L, - .r_ubrrh = UBRR1H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR1B, RXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, RXC1), - .vector = USART1_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR1B, TXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, TXC1), - .vector = USART1_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR1B, UDRIE1), - .raised = AVR_IO_REGBIT(UCSR1A, UDRE1), - .vector = USART1_UDRE_vect, - }, - }, .timer0 = { .name = '0', .disabled = AVR_IO_REGBIT(PRR0,PRTIM0), diff --git a/simavr/cores/sim_mega128.c b/simavr/cores/sim_mega128.c index 0570c64..4236b67 100644 --- a/simavr/cores/sim_mega128.c +++ b/simavr/cores/sim_mega128.c @@ -85,68 +85,10 @@ const struct mcu_t { AVR_IOPORT_DECLARE(f, 'F', F), AVR_IOPORT_DECLARE(g, 'G', G), - .uart0 = { - // no PRUSART .disabled = AVR_IO_REGBIT(PRR,PRUSART0), - .name = '0', - .r_udr = UDR0, - - .txen = AVR_IO_REGBIT(UCSR0B, TXEN0), - .rxen = AVR_IO_REGBIT(UCSR0B, RXEN0), - .ucsz = AVR_IO_REGBITS(UCSR0C, UCSZ00, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR0B, UCSZ02), // 1 bits - - .r_ucsra = UCSR0A, - .r_ucsrb = UCSR0B, - .r_ucsrc = UCSR0C, - .r_ubrrl = UBRR0L, - .r_ubrrh = UBRR0H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR0B, RXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, RXC0), - .vector = USART0_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR0B, TXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, TXC0), - .vector = USART0_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR0B, UDRIE0), - .raised = AVR_IO_REGBIT(UCSR0A, UDRE0), - .vector = USART0_UDRE_vect, - }, - }, - .uart1 = { - // no PRUSART .disabled = AVR_IO_REGBIT(PRR,PRUSART1), - .name = '1', - .r_udr = UDR1, - - .txen = AVR_IO_REGBIT(UCSR1B, TXEN1), - .rxen = AVR_IO_REGBIT(UCSR1B, RXEN1), - .ucsz = AVR_IO_REGBITS(UCSR1C, UCSZ10, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR1B, UCSZ12), // 1 bits - - .r_ucsra = UCSR1A, - .r_ucsrb = UCSR1B, - .r_ucsrc = UCSR1C, - .r_ubrrl = UBRR1L, - .r_ubrrh = UBRR1H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR1B, RXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, RXC1), - .vector = USART1_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR1B, TXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, TXC1), - .vector = USART1_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR1B, UDRIE1), - .raised = AVR_IO_REGBIT(UCSR1A, UDRE1), - .vector = USART1_UDRE_vect, - }, - }, + // no PRUSART + AVR_UARTX_DECLARE(0, 0, 0), + AVR_UARTX_DECLARE(1, 0, 0), + .adc = { .r_admux = ADMUX, .mux = { AVR_IO_REGBIT(ADMUX, MUX0), AVR_IO_REGBIT(ADMUX, MUX1), diff --git a/simavr/cores/sim_mega1280.c b/simavr/cores/sim_mega1280.c index b3353c5..84a26a8 100644 --- a/simavr/cores/sim_mega1280.c +++ b/simavr/cores/sim_mega1280.c @@ -100,132 +100,12 @@ const struct mcu_t { AVR_IOPORT_DECLARE(j, 'J', J), AVR_IOPORT_DECLARE(k, 'K', K), AVR_IOPORT_DECLARE(l, 'L', L), - .uart0 = { - .disabled = AVR_IO_REGBIT(PRR0,PRUSART0), - .name = '0', - .r_udr = UDR0, - - .txen = AVR_IO_REGBIT(UCSR0B, TXEN0), - .rxen = AVR_IO_REGBIT(UCSR0B, RXEN0), - .ucsz = AVR_IO_REGBITS(UCSR0C, UCSZ00, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR0B, UCSZ02), // 1 bits - - .r_ucsra = UCSR0A, - .r_ucsrb = UCSR0B, - .r_ucsrc = UCSR0C, - .r_ubrrl = UBRR0L, - .r_ubrrh = UBRR0H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR0B, RXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, RXC0), - .vector = USART0_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR0B, TXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, TXC0), - .vector = USART0_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR0B, UDRIE0), - .raised = AVR_IO_REGBIT(UCSR0A, UDRE0), - .vector = USART0_UDRE_vect, - }, - }, - .uart1 = { - .disabled = AVR_IO_REGBIT(PRR1,PRUSART1), - .name = '1', - .r_udr = UDR1, - - .txen = AVR_IO_REGBIT(UCSR1B, TXEN1), - .rxen = AVR_IO_REGBIT(UCSR1B, RXEN1), - .ucsz = AVR_IO_REGBITS(UCSR1C, UCSZ10, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR1B, UCSZ12), // 1 bits - - .r_ucsra = UCSR1A, - .r_ucsrb = UCSR1B, - .r_ucsrc = UCSR1C, - .r_ubrrl = UBRR1L, - .r_ubrrh = UBRR1H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR1B, RXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, RXC1), - .vector = USART1_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR1B, TXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, TXC1), - .vector = USART1_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR1B, UDRIE1), - .raised = AVR_IO_REGBIT(UCSR1A, UDRE1), - .vector = USART1_UDRE_vect, - }, - }, - .uart2 = { - .disabled = AVR_IO_REGBIT(PRR1,PRUSART2), - .name = '2', - .r_udr = UDR2, - - .txen = AVR_IO_REGBIT(UCSR2B, TXEN2), - .rxen = AVR_IO_REGBIT(UCSR2B, RXEN2), - .ucsz = AVR_IO_REGBITS(UCSR2C, UCSZ20, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR2B, UCSZ22), // 1 bits - - .r_ucsra = UCSR2A, - .r_ucsrb = UCSR2B, - .r_ucsrc = UCSR2C, - .r_ubrrl = UBRR2L, - .r_ubrrh = UBRR2H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR2B, RXCIE2), - .raised = AVR_IO_REGBIT(UCSR2A, RXC2), - .vector = USART2_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR2B, TXCIE2), - .raised = AVR_IO_REGBIT(UCSR2A, TXC2), - .vector = USART2_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR2B, UDRIE2), - .raised = AVR_IO_REGBIT(UCSR2A, UDRE2), - .vector = USART2_UDRE_vect, - }, - }, + AVR_UARTX_DECLARE(0, PRR0, PRUSART0), + AVR_UARTX_DECLARE(1, PRR1, PRUSART1), + AVR_UARTX_DECLARE(2, PRR1, PRUSART2), + AVR_UARTX_DECLARE(3, PRR1, PRUSART3), - .uart3 = { - .disabled = AVR_IO_REGBIT(PRR1,PRUSART3), - .name = '3', - .r_udr = UDR3, - - .txen = AVR_IO_REGBIT(UCSR3B, TXEN3), - .rxen = AVR_IO_REGBIT(UCSR3B, RXEN3), - .ucsz = AVR_IO_REGBITS(UCSR3C, UCSZ30, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR3B, UCSZ32), // 1 bits - - .r_ucsra = UCSR3A, - .r_ucsrb = UCSR3B, - .r_ucsrc = UCSR3C, - .r_ubrrl = UBRR3L, - .r_ubrrh = UBRR3H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR3B, RXCIE3), - .raised = AVR_IO_REGBIT(UCSR3A, RXC3), - .vector = USART3_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR3B, TXCIE3), - .raised = AVR_IO_REGBIT(UCSR3A, TXC3), - .vector = USART3_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR3B, UDRIE3), - .raised = AVR_IO_REGBIT(UCSR3A, UDRE3), - .vector = USART3_UDRE_vect, - }, - }, .adc = { .r_admux = ADMUX, .mux = { AVR_IO_REGBIT(ADMUX, MUX0), AVR_IO_REGBIT(ADMUX, MUX1), diff --git a/simavr/cores/sim_mega1281.c b/simavr/cores/sim_mega1281.c index 986e989..7c534d1 100644 --- a/simavr/cores/sim_mega1281.c +++ b/simavr/cores/sim_mega1281.c @@ -92,68 +92,10 @@ const struct mcu_t { AVR_IOPORT_DECLARE(e, 'E', E), AVR_IOPORT_DECLARE(f, 'F', F), AVR_IOPORT_DECLARE(g, 'G', G), - .uart0 = { - .disabled = AVR_IO_REGBIT(PRR0,PRUSART0), - .name = '0', - .r_udr = UDR0, - - .txen = AVR_IO_REGBIT(UCSR0B, TXEN0), - .rxen = AVR_IO_REGBIT(UCSR0B, RXEN0), - .ucsz = AVR_IO_REGBITS(UCSR0C, UCSZ00, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR0B, UCSZ02), // 1 bits - - .r_ucsra = UCSR0A, - .r_ucsrb = UCSR0B, - .r_ucsrc = UCSR0C, - .r_ubrrl = UBRR0L, - .r_ubrrh = UBRR0H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR0B, RXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, RXC0), - .vector = USART0_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR0B, TXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, TXC0), - .vector = USART0_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR0B, UDRIE0), - .raised = AVR_IO_REGBIT(UCSR0A, UDRE0), - .vector = USART0_UDRE_vect, - }, - }, - .uart1 = { - .disabled = AVR_IO_REGBIT(PRR1,PRUSART1), - .name = '1', - .r_udr = UDR1, - - .txen = AVR_IO_REGBIT(UCSR1B, TXEN1), - .rxen = AVR_IO_REGBIT(UCSR1B, RXEN1), - .ucsz = AVR_IO_REGBITS(UCSR1C, UCSZ10, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR1B, UCSZ12), // 1 bits - - .r_ucsra = UCSR1A, - .r_ucsrb = UCSR1B, - .r_ucsrc = UCSR1C, - .r_ubrrl = UBRR1L, - .r_ubrrh = UBRR1H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR1B, RXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, RXC1), - .vector = USART1_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR1B, TXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, TXC1), - .vector = USART1_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR1B, UDRIE1), - .raised = AVR_IO_REGBIT(UCSR1A, UDRE1), - .vector = USART1_UDRE_vect, - }, - }, + + AVR_UARTX_DECLARE(0, PRR0, PRUSART0), + AVR_UARTX_DECLARE(1, PRR1, PRUSART1), + .adc = { .r_admux = ADMUX, .mux = { AVR_IO_REGBIT(ADMUX, MUX0), AVR_IO_REGBIT(ADMUX, MUX1), diff --git a/simavr/cores/sim_mega128rfa1.c b/simavr/cores/sim_mega128rfa1.c index 8e62fbf..6f433ee 100644 --- a/simavr/cores/sim_mega128rfa1.c +++ b/simavr/cores/sim_mega128rfa1.c @@ -101,68 +101,9 @@ const struct mcu_t { AVR_IOPORT_DECLARE(f, 'F', F), AVR_IOPORT_DECLARE(g, 'G', G), - .uart0 = { - .disabled = AVR_IO_REGBIT(PRR0,PRUSART0), - .name = '0', - .r_udr = UDR0, - - .txen = AVR_IO_REGBIT(UCSR0B, TXEN0), - .rxen = AVR_IO_REGBIT(UCSR0B, RXEN0), - .ucsz = AVR_IO_REGBITS(UCSR0C, UCSZ00, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR0B, UCSZ02), // 1 bits - - .r_ucsra = UCSR0A, - .r_ucsrb = UCSR0B, - .r_ucsrc = UCSR0C, - .r_ubrrl = UBRR0L, - .r_ubrrh = UBRR0H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR0B, RXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, RXC0), - .vector = USART0_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR0B, TXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, TXC0), - .vector = USART0_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR0B, UDRIE0), - .raised = AVR_IO_REGBIT(UCSR0A, UDRE0), - .vector = USART0_UDRE_vect, - }, - }, - .uart1 = { - .disabled = AVR_IO_REGBIT(PRR1,PRUSART1), - .name = '1', - .r_udr = UDR1, - - .txen = AVR_IO_REGBIT(UCSR1B, TXEN1), - .rxen = AVR_IO_REGBIT(UCSR1B, RXEN1), - .ucsz = AVR_IO_REGBITS(UCSR1C, UCSZ10, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR1B, UCSZ12), // 1 bits - - .r_ucsra = UCSR1A, - .r_ucsrb = UCSR1B, - .r_ucsrc = UCSR1C, - .r_ubrrl = UBRR1L, - .r_ubrrh = UBRR1H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR1B, RXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, RXC1), - .vector = USART1_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR1B, TXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, TXC1), - .vector = USART1_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR1B, UDRIE1), - .raised = AVR_IO_REGBIT(UCSR1A, UDRE1), - .vector = USART1_UDRE_vect, - }, - }, + AVR_UARTX_DECLARE(0, PRR0, PRUSART0), + AVR_UARTX_DECLARE(1, PRR1, PRUSART1), + .adc = { .r_admux = ADMUX, .mux = { AVR_IO_REGBIT(ADMUX, MUX0), AVR_IO_REGBIT(ADMUX, MUX1), diff --git a/simavr/cores/sim_mega128rfr2.c b/simavr/cores/sim_mega128rfr2.c index 62271df..c69907d 100644 --- a/simavr/cores/sim_mega128rfr2.c +++ b/simavr/cores/sim_mega128rfr2.c @@ -127,68 +127,9 @@ const struct mcu_t { AVR_IOPORT_DECLARE(f, 'F', F), AVR_IOPORT_DECLARE(g, 'G', G), - .uart0 = { - .disabled = AVR_IO_REGBIT(PRR0,PRUSART0), - .name = '0', - .r_udr = UDR0, - - .txen = AVR_IO_REGBIT(UCSR0B, TXEN0), - .rxen = AVR_IO_REGBIT(UCSR0B, RXEN0), - .ucsz = AVR_IO_REGBITS(UCSR0C, UCSZ00, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR0B, UCSZ02), // 1 bits - - .r_ucsra = UCSR0A, - .r_ucsrb = UCSR0B, - .r_ucsrc = UCSR0C, - .r_ubrrl = UBRR0L, - .r_ubrrh = UBRR0H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR0B, RXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, RXC0), - .vector = USART0_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR0B, TXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, TXC0), - .vector = USART0_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR0B, UDRIE0), - .raised = AVR_IO_REGBIT(UCSR0A, UDRE0), - .vector = USART0_UDRE_vect, - }, - }, - .uart1 = { - .disabled = AVR_IO_REGBIT(PRR1,PRUSART1), - .name = '1', - .r_udr = UDR1, - - .txen = AVR_IO_REGBIT(UCSR1B, TXEN1), - .rxen = AVR_IO_REGBIT(UCSR1B, RXEN1), - .ucsz = AVR_IO_REGBITS(UCSR1C, UCSZ10, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR1B, UCSZ12), // 1 bits - - .r_ucsra = UCSR1A, - .r_ucsrb = UCSR1B, - .r_ucsrc = UCSR1C, - .r_ubrrl = UBRR1L, - .r_ubrrh = UBRR1H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR1B, RXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, RXC1), - .vector = USART1_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR1B, TXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, TXC1), - .vector = USART1_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR1B, UDRIE1), - .raised = AVR_IO_REGBIT(UCSR1A, UDRE1), - .vector = USART1_UDRE_vect, - }, - }, + AVR_UARTX_DECLARE(0, PRR0, PRUSART0), + AVR_UARTX_DECLARE(1, PRR1, PRUSART1), + .adc = { .r_admux = ADMUX, .mux = { AVR_IO_REGBIT(ADMUX, MUX0), AVR_IO_REGBIT(ADMUX, MUX1), diff --git a/simavr/cores/sim_mega169.c b/simavr/cores/sim_mega169.c index 4af93a6..c72e96e 100644 --- a/simavr/cores/sim_mega169.c +++ b/simavr/cores/sim_mega169.c @@ -77,36 +77,8 @@ const struct mcu_t { AVR_IOPORT_DECLARE(f, 'F', F), AVR_IOPORT_DECLARE(g, 'G', G), - .uart0 = { - .name = '0', - .r_udr = UDR0, - - .txen = AVR_IO_REGBIT(UCSR0B, TXEN0), - .rxen = AVR_IO_REGBIT(UCSR0B, RXEN0), - .ucsz = AVR_IO_REGBITS(UCSR0C, UCSZ00, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR0B, UCSZ02), // 1 bits - - .r_ucsra = UCSR0A, - .r_ucsrb = UCSR0B, - .r_ucsrc = UCSR0C, - .r_ubrrl = UBRR0L, - .r_ubrrh = UBRR0H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR0B, RXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, RXC0), - .vector = USART0_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR0B, TXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, TXC0), - .vector = USART0_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR0B, UDRIE0), - .raised = AVR_IO_REGBIT(UCSR0A, UDRE0), - .vector = USART0_UDRE_vect, - }, - }, + AVR_UARTX_DECLARE(0, PRR, PRUSART0), + .adc = { .r_admux = ADMUX, .mux = { AVR_IO_REGBIT(ADMUX, MUX0), AVR_IO_REGBIT(ADMUX, MUX1), diff --git a/simavr/cores/sim_mega2560.c b/simavr/cores/sim_mega2560.c index c1383a2..8e09e71 100644 --- a/simavr/cores/sim_mega2560.c +++ b/simavr/cores/sim_mega2560.c @@ -102,132 +102,12 @@ const struct mcu_t { AVR_IOPORT_DECLARE(j, 'J', J), AVR_IOPORT_DECLARE(k, 'K', K), AVR_IOPORT_DECLARE(l, 'L', L), - .uart0 = { - .disabled = AVR_IO_REGBIT(PRR0,PRUSART0), - .name = '0', - .r_udr = UDR0, - - .txen = AVR_IO_REGBIT(UCSR0B, TXEN0), - .rxen = AVR_IO_REGBIT(UCSR0B, RXEN0), - .ucsz = AVR_IO_REGBITS(UCSR0C, UCSZ00, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR0B, UCSZ02), // 1 bits - - .r_ucsra = UCSR0A, - .r_ucsrb = UCSR0B, - .r_ucsrc = UCSR0C, - .r_ubrrl = UBRR0L, - .r_ubrrh = UBRR0H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR0B, RXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, RXC0), - .vector = USART0_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR0B, TXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, TXC0), - .vector = USART0_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR0B, UDRIE0), - .raised = AVR_IO_REGBIT(UCSR0A, UDRE0), - .vector = USART0_UDRE_vect, - }, - }, - .uart1 = { - .disabled = AVR_IO_REGBIT(PRR1,PRUSART1), - .name = '1', - .r_udr = UDR1, - - .txen = AVR_IO_REGBIT(UCSR1B, TXEN1), - .rxen = AVR_IO_REGBIT(UCSR1B, RXEN1), - .ucsz = AVR_IO_REGBITS(UCSR1C, UCSZ10, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR1B, UCSZ12), // 1 bits - - .r_ucsra = UCSR1A, - .r_ucsrb = UCSR1B, - .r_ucsrc = UCSR1C, - .r_ubrrl = UBRR1L, - .r_ubrrh = UBRR1H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR1B, RXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, RXC1), - .vector = USART1_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR1B, TXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, TXC1), - .vector = USART1_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR1B, UDRIE1), - .raised = AVR_IO_REGBIT(UCSR1A, UDRE1), - .vector = USART1_UDRE_vect, - }, - }, - .uart2 = { - .disabled = AVR_IO_REGBIT(PRR1,PRUSART2), - .name = '2', - .r_udr = UDR2, - - .txen = AVR_IO_REGBIT(UCSR2B, TXEN2), - .rxen = AVR_IO_REGBIT(UCSR2B, RXEN2), - .ucsz = AVR_IO_REGBITS(UCSR2C, UCSZ20, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR2B, UCSZ22), // 1 bits - - .r_ucsra = UCSR2A, - .r_ucsrb = UCSR2B, - .r_ucsrc = UCSR2C, - .r_ubrrl = UBRR2L, - .r_ubrrh = UBRR2H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR2B, RXCIE2), - .raised = AVR_IO_REGBIT(UCSR2A, RXC2), - .vector = USART2_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR2B, TXCIE2), - .raised = AVR_IO_REGBIT(UCSR2A, TXC2), - .vector = USART2_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR2B, UDRIE2), - .raised = AVR_IO_REGBIT(UCSR2A, UDRE2), - .vector = USART2_UDRE_vect, - }, - }, + AVR_UARTX_DECLARE(0, PRR0, PRUSART0), + AVR_UARTX_DECLARE(1, PRR1, PRUSART1), + AVR_UARTX_DECLARE(2, PRR1, PRUSART2), + AVR_UARTX_DECLARE(3, PRR1, PRUSART3), - .uart3 = { - .disabled = AVR_IO_REGBIT(PRR1,PRUSART3), - .name = '3', - .r_udr = UDR3, - - .txen = AVR_IO_REGBIT(UCSR3B, TXEN3), - .rxen = AVR_IO_REGBIT(UCSR3B, RXEN3), - .ucsz = AVR_IO_REGBITS(UCSR3C, UCSZ30, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR3B, UCSZ32), // 1 bits - - .r_ucsra = UCSR3A, - .r_ucsrb = UCSR3B, - .r_ucsrc = UCSR3C, - .r_ubrrl = UBRR3L, - .r_ubrrh = UBRR3H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR3B, RXCIE3), - .raised = AVR_IO_REGBIT(UCSR3A, RXC3), - .vector = USART3_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR3B, TXCIE3), - .raised = AVR_IO_REGBIT(UCSR3A, TXC3), - .vector = USART3_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR3B, UDRIE3), - .raised = AVR_IO_REGBIT(UCSR3A, UDRE3), - .vector = USART3_UDRE_vect, - }, - }, .adc = { .r_admux = ADMUX, .mux = { AVR_IO_REGBIT(ADMUX, MUX0), AVR_IO_REGBIT(ADMUX, MUX1), diff --git a/simavr/cores/sim_megax.h b/simavr/cores/sim_megax.h index a6c14f8..81c26f5 100644 --- a/simavr/cores/sim_megax.h +++ b/simavr/cores/sim_megax.h @@ -98,37 +98,10 @@ const struct mcu_t SIM_CORENAME = { AVR_IOPORT_DECLARE(b, 'B', B), AVR_IOPORT_DECLARE(c, 'C', C), AVR_IOPORT_DECLARE(d, 'D', D), - .uart = { - // no PRUSART .disabled = AVR_IO_REGBIT(PRR,PRUSART0), - .name = '0', - .r_udr = UDR, - - .txen = AVR_IO_REGBIT(UCSRB, TXEN), - .rxen = AVR_IO_REGBIT(UCSRB, RXEN), - .ucsz = AVR_IO_REGBITS(UCSRC, UCSZ0, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSRB, UCSZ2), // 1 bits - - .r_ucsra = UCSRA, - .r_ucsrb = UCSRB, - .r_ucsrc = UCSRC, - .r_ubrrl = UBRRL, - .r_ubrrh = UBRRH, - .rxc = { - .enable = AVR_IO_REGBIT(UCSRB, RXCIE), - .raised = AVR_IO_REGBIT(UCSRA, RXC), - .vector = USART_RXC_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSRB, TXCIE), - .raised = AVR_IO_REGBIT(UCSRA, TXC), - .vector = USART_TXC_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSRB, UDRIE), - .raised = AVR_IO_REGBIT(UCSRA, UDRE), - .vector = USART_UDRE_vect, - }, - }, + + //no PRUSART, upe=PE, no reg/bit name index, 'C' in RX/TX vector names + AVR_UART_DECLARE(0, 0, PE, , C), + .adc = { .r_admux = ADMUX, .mux = { AVR_IO_REGBIT(ADMUX, MUX0), AVR_IO_REGBIT(ADMUX, MUX1), diff --git a/simavr/cores/sim_megax4.h b/simavr/cores/sim_megax4.h index 9a22b85..2688692 100644 --- a/simavr/cores/sim_megax4.h +++ b/simavr/cores/sim_megax4.h @@ -128,70 +128,9 @@ const struct mcu_t SIM_CORENAME = { .r_pcint = PCMSK3, }, - .uart0 = { - .disabled = AVR_IO_REGBIT(PRR0,PRUSART0), - .name = '0', - .r_udr = UDR0, - - .u2x = AVR_IO_REGBIT(UCSR0A, U2X0), - .txen = AVR_IO_REGBIT(UCSR0B, TXEN0), - .rxen = AVR_IO_REGBIT(UCSR0B, RXEN0), - .ucsz = AVR_IO_REGBITS(UCSR0C, UCSZ00, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR0B, UCSZ02), // 1 bits - - .r_ucsra = UCSR0A, - .r_ucsrb = UCSR0B, - .r_ucsrc = UCSR0C, - .r_ubrrl = UBRR0L, - .r_ubrrh = UBRR0H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR0B, RXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, RXC0), - .vector = USART0_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR0B, TXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, TXC0), - .vector = USART0_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR0B, UDRIE0), - .raised = AVR_IO_REGBIT(UCSR0A, UDRE0), - .vector = USART0_UDRE_vect, - }, - }, - .uart1 = { - .disabled = AVR_IO_REGBIT(PRR0,PRUSART1), - .name = '1', - .r_udr = UDR1, - - .u2x = AVR_IO_REGBIT(UCSR1A, U2X1), - .txen = AVR_IO_REGBIT(UCSR1B, TXEN1), - .rxen = AVR_IO_REGBIT(UCSR1B, RXEN1), - .ucsz = AVR_IO_REGBITS(UCSR1C, UCSZ10, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR1B, UCSZ12), // 1 bits - - .r_ucsra = UCSR1A, - .r_ucsrb = UCSR1B, - .r_ucsrc = UCSR1C, - .r_ubrrl = UBRR1L, - .r_ubrrh = UBRR1H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR1B, RXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, RXC1), - .vector = USART1_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR1B, TXCIE1), - .raised = AVR_IO_REGBIT(UCSR1A, TXC1), - .vector = USART1_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR1B, UDRIE1), - .raised = AVR_IO_REGBIT(UCSR1A, UDRE1), - .vector = USART1_UDRE_vect, - }, - }, + AVR_UARTX_DECLARE(0, PRR0, PRUSART0), + AVR_UARTX_DECLARE(1, PRR0, PRUSART1), + .adc = { // .disabled = AVR_IO_REGBIT(PRR0,PRADC), .r_admux = ADMUX, diff --git a/simavr/cores/sim_megax8.h b/simavr/cores/sim_megax8.h index 06723ea..f9661ab 100644 --- a/simavr/cores/sim_megax8.h +++ b/simavr/cores/sim_megax8.h @@ -117,38 +117,9 @@ const struct mcu_t SIM_CORENAME = { .r_pcint = PCMSK2, }, - .uart = { - .disabled = AVR_IO_REGBIT(PRR,PRUSART0), - .name = '0', - .r_udr = UDR0, - - .txen = AVR_IO_REGBIT(UCSR0B, TXEN0), - .rxen = AVR_IO_REGBIT(UCSR0B, RXEN0), - .usbs = AVR_IO_REGBIT(UCSR0C, USBS0), - .ucsz = AVR_IO_REGBITS(UCSR0C, UCSZ00, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSR0B, UCSZ02), // 1 bits - - .r_ucsra = UCSR0A, - .r_ucsrb = UCSR0B, - .r_ucsrc = UCSR0C, - .r_ubrrl = UBRR0L, - .r_ubrrh = UBRR0H, - .rxc = { - .enable = AVR_IO_REGBIT(UCSR0B, RXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, RXC0), - .vector = USART_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSR0B, TXCIE0), - .raised = AVR_IO_REGBIT(UCSR0A, TXC0), - .vector = USART_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSR0B, UDRIE0), - .raised = AVR_IO_REGBIT(UCSR0A, UDRE0), - .vector = USART_UDRE_vect, - }, - }, + //PRR/PRUSART0, upe=UPE, reg/bit name index=0, no 'C' in RX/TX vector names + AVR_UART_DECLARE(PRR, PRUSART0, UPE, 0, ), + .adc = { .r_admux = ADMUX, .mux = { AVR_IO_REGBIT(ADMUX, MUX0), AVR_IO_REGBIT(ADMUX, MUX1), diff --git a/simavr/cores/sim_tiny2313.c b/simavr/cores/sim_tiny2313.c index 43d2543..6cb8366 100644 --- a/simavr/cores/sim_tiny2313.c +++ b/simavr/cores/sim_tiny2313.c @@ -70,38 +70,10 @@ static const struct mcu_t { .r_pcint = PCMSK, }, AVR_IOPORT_DECLARE(d, 'D', D), // port D has no PCInts.. - .uart = { - // no PRR register on the 2313 - //.disabled = AVR_IO_REGBIT(PRR,PRUSART0), - .name = '0', - .r_udr = UDR, - - .txen = AVR_IO_REGBIT(UCSRB, TXEN), - .rxen = AVR_IO_REGBIT(UCSRB, RXEN), - .ucsz = AVR_IO_REGBITS(UCSRC, UCSZ0, 0x3), // 2 bits - .ucsz2 = AVR_IO_REGBIT(UCSRB, UCSZ2), // 1 bits - - .r_ucsra = UCSRA, - .r_ucsrb = UCSRB, - .r_ucsrc = UCSRC, - .r_ubrrl = UBRRL, - .r_ubrrh = UBRRH, - .rxc = { - .enable = AVR_IO_REGBIT(UCSRB, RXCIE), - .raised = AVR_IO_REGBIT(UCSRA, RXC), - .vector = USART_RX_vect, - }, - .txc = { - .enable = AVR_IO_REGBIT(UCSRB, TXCIE), - .raised = AVR_IO_REGBIT(UCSRA, TXC), - .vector = USART_TX_vect, - }, - .udrc = { - .enable = AVR_IO_REGBIT(UCSRB, UDRIE), - .raised = AVR_IO_REGBIT(UCSRA, UDRE), - .vector = USART_UDRE_vect, - }, - }, + + //no PRUSART, upe=UPE, no reg/bit name index, no 'C' in RX/TX vector names + AVR_UART_DECLARE(0, 0, UPE, , ), + .timer0 = { .name = '0', .wgm = { AVR_IO_REGBIT(TCCR0A, WGM00), AVR_IO_REGBIT(TCCR0A, WGM01), AVR_IO_REGBIT(TCCR0B, WGM02) }, diff --git a/simavr/sim/avr_lin.c b/simavr/sim/avr_lin.c index 1d397d5..001b34c 100644 --- a/simavr/sim/avr_lin.c +++ b/simavr/sim/avr_lin.c @@ -22,6 +22,7 @@ #include #include "avr_lin.h" +#include "sim_time.h" static void @@ -59,14 +60,18 @@ avr_lin_baud_write( uint32_t lbrr = (avr->data[p->r_linbrrh] << 8) | avr->data[p->r_linbrrl]; AVR_LOG(avr, LOG_TRACE, "LIN: UART LBT/LBRR to %04x/%04x\n", lbt, lbrr); // there is no division by zero case here, lbt is >= 8 - uint32_t baud = avr->frequency / (lbt * (lbrr + 1)); + //uint32_t baud = avr->frequency / (lbt * (lbrr + 1)); uint32_t word_size = 1 /*start*/+ 8 /*data bits*/+ 1 /*parity*/+ 1 /*stop*/; + int cycles_per_bit = lbt * (lbrr + 1); + double baud = ((double)avr->frequency) / cycles_per_bit; // can be less than 1 + p->uart.cycles_per_byte = cycles_per_bit * word_size; - AVR_LOG(avr, LOG_TRACE, "LIN: UART configured to %04x/%04x = %d bps, 8 data 1 stop\n", lbt, + AVR_LOG(avr, LOG_TRACE, "LIN: UART configured to %04x/%04x = %.4f bps, 8 data 1 stop\n", lbt, lbrr, baud); - p->uart.usec_per_byte = 1000000 / (baud / word_size); - AVR_LOG(avr, LOG_TRACE, "LIN: Roughly %d usec per bytes\n", (int) p->uart.usec_per_byte); + //p->uart.cycles_per_byte = 1000000 / (baud / word_size); + AVR_LOG(avr, LOG_TRACE, "LIN: Roughly %d usec per byte\n", + avr_cycles_to_usec(avr, p->uart.cycles_per_byte)); } static void diff --git a/simavr/sim/avr_uart.c b/simavr/sim/avr_uart.c index 2a69c16..bb4bc15 100644 --- a/simavr/sim/avr_uart.c +++ b/simavr/sim/avr_uart.c @@ -37,6 +37,8 @@ #include #include "avr_uart.h" #include "sim_hex.h" +#include "sim_time.h" +#include "sim_gdb.h" //#define TRACE(_w) _w #ifndef TRACE @@ -45,22 +47,72 @@ DEFINE_FIFO(uint8_t, uart_fifo); +static inline void avr_uart_clear_interrupt( + avr_t * avr, + avr_int_vector_t * vector) +{ + if (!vector->vector) + return; + // clear the interrupt flag even it's 'sticky' + if (avr_regbit_get(avr, vector->raised)) + avr_clear_interrupt_if(avr, vector, 0); + if (avr_regbit_get(avr, vector->raised)) + avr_regbit_clear(avr, vector->raised); +} + +static inline void avr_uart_regbit_clear(avr_t * avr, avr_regbit_t rb) +{ + uint16_t a = rb.reg; + if (!a) + return; + avr_regbit_clear(avr, rb); +} + static avr_cycle_count_t avr_uart_txc_raise(struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_uart_t * p = (avr_uart_t *)param; - if (avr_regbit_get(avr, p->txen)) { - // if the interrupts are not used, still raise the UDRE and TXC flag - avr_raise_interrupt(avr, &p->udrc); - avr_raise_interrupt(avr, &p->txc); + if (p->tx_cnt) { + // Even if the interrupt is disabled, still raise the TXC flag + if (p->tx_cnt == 1) + avr_raise_interrupt(avr, &p->txc); + p->tx_cnt--; } - return 0; + if (p->udrc.vector) {// UDRE is disabled in the LIN mode + if (p->tx_cnt) { + if (avr_regbit_get(avr, p->udrc.raised)) { + avr_uart_clear_interrupt(avr, &p->udrc); + } + } else { + if (avr_regbit_get(avr, p->txen)) { + // Even if the interrupt is disabled, still raise the UDRE flag + avr_raise_interrupt(avr, &p->udrc); + if (!avr_regbit_get(avr, p->udrc.enable)) { + return 0; //polling mode: stop TX pump + } else // udrc (alias udre) should be rased repeatedly while output buffer is empty + return when + p->cycles_per_byte; + } else + return 0; // transfer disabled: stop TX pump + } + } + if (p->tx_cnt) + return when + p->cycles_per_byte; + return 0; // stop TX pump } static avr_cycle_count_t avr_uart_rxc_raise(struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_uart_t * p = (avr_uart_t *)param; - if (avr_regbit_get(avr, p->rxen)) - avr_raise_interrupt(avr, &p->rxc); + if (avr_regbit_get(avr, p->rxen)) { + // rxc should be rased continiosly untill input buffer is empty + if (!uart_fifo_isempty(&p->input)) { + if (!avr_regbit_get(avr, p->rxc.raised)) { + p->rxc_raise_time = when; + p->rx_cnt = 0; + } + avr_raise_interrupt(avr, &p->rxc); + return when + p->cycles_per_byte; + } + } return 0; } @@ -80,7 +132,7 @@ static uint8_t avr_uart_rxc_read(struct avr_t * avr, avr_io_addr_t addr, void * uint8_t ri = !avr_regbit_get(avr, p->rxen) || !avr_regbit_get(avr, p->rxc.raised); uint8_t ti = !avr_regbit_get(avr, p->txen) || !avr_regbit_get(avr, p->txc.raised); - if (p->flags & AVR_UART_FLAG_POOL_SLEEP) { + if (p->flags & AVR_UART_FLAG_POLL_SLEEP) { if (ri && ti) usleep(1); @@ -97,27 +149,46 @@ static uint8_t avr_uart_rxc_read(struct avr_t * avr, avr_io_addr_t addr, void * static uint8_t avr_uart_read(struct avr_t * avr, avr_io_addr_t addr, void * param) { avr_uart_t * p = (avr_uart_t *)param; + uint8_t v = 0; - // clear the rxc interrupt in case the code is using polling - uint8_t rxc = avr_regbit_get(avr, p->rxc.raised); - avr_clear_interrupt_if(avr, &p->rxc, rxc); - - if (!avr_regbit_get(avr, p->rxen)) { + if (!avr_regbit_get(avr, p->rxen) || + !avr_regbit_get(avr, p->rxc.raised) // rxc flag not raised - nothing to read! + ) { + AVR_LOG(avr, LOG_TRACE, "UART%c: attempt to read empty rx buffer\n", p->name); avr->data[addr] = 0; // made to trigger potential watchpoints avr_core_watch_read(avr, addr); - return 0; + //return 0; + goto avr_uart_read_check; + } + if (!uart_fifo_isempty(&p->input)) { // probably redundant check + v = uart_fifo_read(&p->input); + p->rx_cnt++; + if ((p->rx_cnt > 1) && // UART actually has 2-character rx buffer + ((avr->cycle-p->rxc_raise_time)/p->rx_cnt < p->cycles_per_byte)) { + // prevent the firmware from reading input characters with non-realistic high speed + avr_uart_clear_interrupt(avr, &p->rxc); + p->rx_cnt = 0; + } + } else { + AVR_LOG(avr, LOG_TRACE, "UART%c: BUG: rxc raised with empty rx buffer\n", p->name); } - uint8_t v = uart_fifo_read(&p->input); // TRACE(printf("UART read %02x %s\n", v, uart_fifo_isempty(&p->input) ? "EMPTY!" : "");) avr->data[addr] = v; // made to trigger potential watchpoints v = avr_core_watch_read(avr, addr); - // trigger timer if more characters are pending - if (!uart_fifo_isempty(&p->input)) - avr_cycle_timer_register_usec(avr, p->usec_per_byte, avr_uart_rxc_raise, p); +avr_uart_read_check: + if (uart_fifo_isempty(&p->input)) { + avr_cycle_timer_cancel(avr, avr_uart_rxc_raise, p); + avr_uart_clear_interrupt(avr, &p->rxc); + avr_raise_irq(p->io.irq + UART_IRQ_OUT_XOFF, 0); + avr_raise_irq(p->io.irq + UART_IRQ_OUT_XON, 1); + } + if (!uart_fifo_isfull(&p->input)) { + avr_uart_regbit_clear(avr, p->dor); + } return v; } @@ -127,34 +198,38 @@ static void avr_uart_baud_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t avr_uart_t * p = (avr_uart_t *)param; avr_core_watch_write(avr, addr, v); uint32_t val = avr->data[p->r_ubrrl] | (avr->data[p->r_ubrrh] << 8); - uint32_t baud = avr->frequency / (val+1); - if (avr_regbit_get(avr, p->u2x)) - baud /= 8; - else - baud /= 16; const int databits[] = { 5,6,7,8, /* 'reserved', assume 8 */8,8,8, 9 }; int db = databits[avr_regbit_get(avr, p->ucsz) | (avr_regbit_get(avr, p->ucsz2) << 2)]; int sb = 1 + avr_regbit_get(avr, p->usbs); int word_size = 1 /* start */ + db /* data bits */ + 1 /* parity */ + sb /* stops */; + int cycles_per_bit = (val+1)*8; + if (!avr_regbit_get(avr, p->u2x)) + cycles_per_bit *= 2; + double baud = ((double)avr->frequency) / cycles_per_bit; // can be less than 1 + p->cycles_per_byte = cycles_per_bit * word_size; - AVR_LOG(avr, LOG_TRACE, "UART: %c configured to %04x = %d bps (x%d), %d data %d stop\n", + AVR_LOG(avr, LOG_TRACE, "UART: %c configured to %04x = %.4f bps (x%d), %d data %d stop\n", p->name, val, baud, avr_regbit_get(avr, p->u2x)?2:1, db, sb); - // TODO: Use the divider value and calculate the straight number of cycles - p->usec_per_byte = 1000000 / (baud / word_size); - AVR_LOG(avr, LOG_TRACE, "UART: Roughly %d usec per bytes\n", (int)p->usec_per_byte); + AVR_LOG(avr, LOG_TRACE, "UART: Roughly %d usec per byte\n", + avr_cycles_to_usec(avr, p->cycles_per_byte)); } static void avr_uart_udr_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) { avr_uart_t * p = (avr_uart_t *)param; - avr_core_watch_write(avr, addr, v); + // The byte to be sent should NOT be writen there, + // the value writen could never be read back. + //avr_core_watch_write(avr, addr, v); + if (avr->gdb) { + avr_gdb_handle_watchpoints(avr, addr, AVR_GDB_WATCH_WRITE); + } - if ( p->udrc.vector) - avr_regbit_clear(avr, p->udrc.raised); - avr_cycle_timer_register_usec(avr, - p->usec_per_byte, avr_uart_txc_raise, p); // should be uart speed dependent + //avr_cycle_timer_cancel(avr, avr_uart_txc_raise, p); // synchronize tx pump + if (p->udrc.vector && avr_regbit_get(avr, p->udrc.raised)) { + avr_uart_clear_interrupt(avr, &p->udrc); + } if (p->flags & AVR_UART_FLAG_STDIO) { const int maxsize = 256; @@ -169,8 +244,14 @@ static void avr_uart_udr_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v } TRACE(printf("UDR%c(%02x) = %02x\n", p->name, addr, v);) // tell other modules we are "outputting" a byte - if (avr_regbit_get(avr, p->txen)) + if (avr_regbit_get(avr, p->txen)) { avr_raise_irq(p->io.irq + UART_IRQ_OUTPUT, v); + p->tx_cnt++; + if (p->tx_cnt > 2) // AVR actually has 1-character UART tx buffer, plus shift register + AVR_LOG(avr, LOG_TRACE, "UART%c: tx buffer overflow %d\n", p->name, (int)p->tx_cnt); + if (avr_cycle_timer_status(avr, avr_uart_txc_raise, p) == 0) + avr_cycle_timer_register(avr, p->cycles_per_byte, avr_uart_txc_raise, p); // start the tx pump + } } @@ -178,34 +259,96 @@ static void avr_uart_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, vo { avr_uart_t * p = (avr_uart_t *)param; - if (p->udrc.vector && addr == p->udrc.enable.reg) { - /* - * If enabling the UDRC interrupt, raise it immediately if FIFO is empty - */ - uint8_t udrce = avr_regbit_get(avr, p->udrc.enable); - avr_core_watch_write(avr, addr, v); - uint8_t nudrce = avr_regbit_get(avr, p->udrc.enable); - if (!udrce && nudrce) { - // if the FIDO is not empty (clear timer is flying) we don't - // need to raise the interrupt, it will happen when the timer - // is fired. - if (avr_cycle_timer_status(avr, avr_uart_txc_raise, p) == 0) - avr_raise_interrupt(avr, &p->udrc); + uint8_t masked_v = v; + uint8_t clear_txc = 0; + uint8_t clear_rxc = 0; + + // exclude these locations from direct write: + if (p->udrc.raised.reg == addr) { + masked_v &= ~(p->udrc.raised.mask << p->udrc.raised.bit); + masked_v |= avr_regbit_get_raw(avr, p->udrc.raised); + } + if (p->txc.raised.reg == addr) { + uint8_t mask = p->txc.raised.mask << p->txc.raised.bit; + masked_v &= ~(mask); + masked_v |= avr_regbit_get_raw(avr, p->txc.raised); + // it can be cleared by writing a one to its bit location + if (v & mask) + clear_txc = 1; + } + if (p->rxc.raised.reg == addr) { + uint8_t mask = p->rxc.raised.mask << p->rxc.raised.bit; + masked_v &= ~(mask); + masked_v |= avr_regbit_get_raw(avr, p->rxc.raised); + if (!p->udrc.vector) { + // In the LIN mode it can be cleared by writing a one to its bit location + if (v & mask) + clear_rxc = 1; + } + } + // mainly to prevent application to confuse itself + // by writing something there and reading it back: + if (p->fe.reg == addr) { + masked_v &= ~(p->fe.mask << p->fe.bit); + masked_v |= avr_regbit_get_raw(avr, p->fe); + } + if (p->dor.reg == addr) { + masked_v &= ~(p->dor.mask << p->dor.bit); + //masked_v |= avr_regbit_get_raw(avr, p->dor); + } + if (p->upe.reg == addr) { + masked_v &= ~(p->upe.mask << p->upe.bit); + masked_v |= avr_regbit_get_raw(avr, p->upe); + } + if (p->rxb8.reg == addr) { + masked_v &= ~(p->rxb8.mask << p->rxb8.bit); + masked_v |= avr_regbit_get_raw(avr, p->rxb8); + } + + uint8_t txen = avr_regbit_get(avr, p->txen); + uint8_t rxen = avr_regbit_get(avr, p->rxen); + uint8_t udrce = avr_regbit_get(avr, p->udrc.enable); + // Now write whatever bits could be writen directly. + // It is necessary anyway, to trigger potential watchpoints. + avr_core_watch_write(avr, addr, masked_v); + uint8_t new_txen = avr_regbit_get(avr, p->txen); + uint8_t new_rxen = avr_regbit_get(avr, p->rxen); + uint8_t new_udrce = avr_regbit_get(avr, p->udrc.enable); + if (p->udrc.vector && (!udrce && new_udrce) && new_txen) { + // If enabling the UDRC (alias is UDRE) interrupt, raise it immediately if FIFO is empty. + // If the FIFO is not empty (clear timer is flying) we don't + // need to raise the interrupt, it will happen when the timer + // is fired. + if (avr_cycle_timer_status(avr, avr_uart_txc_raise, p) == 0) + avr_raise_interrupt(avr, &p->udrc); + } + if (clear_txc) + avr_uart_clear_interrupt(avr, &p->txc); + if (clear_rxc) + avr_uart_clear_interrupt(avr, &p->rxc); + + ///TODO: handle the RxD & TxD pins function override + + if (new_rxen != rxen) { + if (new_rxen) { + if (uart_fifo_isempty(&p->input)) { + // if reception is enabled and the fifo is empty, tell whomever there is room + avr_raise_irq(p->io.irq + UART_IRQ_OUT_XOFF, 0); + avr_raise_irq(p->io.irq + UART_IRQ_OUT_XON, 1); + } + } else { + avr_raise_irq(p->io.irq + UART_IRQ_OUT_XOFF, 1); + avr_cycle_timer_cancel(avr, avr_uart_rxc_raise, p); + // flush the Receive Buffer + uart_fifo_reset(&p->input); + // clear the rxc interrupt flag + avr_uart_clear_interrupt(avr, &p->rxc); } } - if (p->udrc.vector && addr == p->udrc.raised.reg) { - // get the bits before the write - //uint8_t udre = avr_regbit_get(avr, p->udrc.raised); - uint8_t txc = avr_regbit_get(avr, p->txc.raised); - - // setting u2x (double uart transmission speed) may also involve - // overwriting read only flags, therefore set u2x explicitly. - if(addr == p->u2x.reg) { - avr_regbit_setto_raw(avr, p->u2x, v); - } - - //avr_clear_interrupt_if(avr, &p->udrc, udre); - avr_clear_interrupt_if(avr, &p->txc, txc); + if (new_txen != txen) { + if (p->udrc.vector && !new_txen) { + avr_uart_clear_interrupt(avr, &p->udrc); + } } } @@ -218,9 +361,27 @@ static void avr_uart_irq_input(struct avr_irq_t * irq, uint32_t value, void * pa if (!avr_regbit_get(avr, p->rxen)) return; - if (uart_fifo_isempty(&p->input)) - avr_cycle_timer_register_usec(avr, p->usec_per_byte, avr_uart_rxc_raise, p); // should be uart speed dependent - uart_fifo_write(&p->input, value); // add to fifo + // reserved/not implemented: + //avr_uart_regbit_clear(avr, p->fe); + //avr_uart_regbit_clear(avr, p->upe); + //avr_uart_regbit_clear(avr, p->rxb8); + + if (uart_fifo_isempty(&p->input) && + (avr_cycle_timer_status(avr, avr_uart_rxc_raise, p) == 0) + ) { + avr_cycle_timer_register(avr, p->cycles_per_byte, avr_uart_rxc_raise, p); // start the rx pump + p->rx_cnt = 0; + avr_uart_regbit_clear(avr, p->dor); + } else if (uart_fifo_isfull(&p->input)) { + avr_regbit_setto(avr, p->dor, 1); + } + if (!avr_regbit_get(avr, p->dor)) { // otherwise newly received character must be rejected + uart_fifo_write(&p->input, value); // add to fifo + } else { + AVR_LOG(avr, LOG_ERROR, "UART%c: %s: RX buffer overrun, lost char=%c=0x%02X\n", p->name, __func__, + (char)value, (uint8_t)value + ); + } TRACE(printf("UART IRQ in %02x (%d/%d) %s\n", value, p->input.read, p->input.write, uart_fifo_isfull(&p->input) ? "FULL!!" : "");) @@ -233,19 +394,24 @@ void avr_uart_reset(struct avr_io_t *io) { avr_uart_t * p = (avr_uart_t *)io; avr_t * avr = p->io.avr; - if (p->udrc.vector) + if (p->udrc.vector) { avr_regbit_set(avr, p->udrc.raised); + avr_uart_regbit_clear(avr, p->dor); + } + avr_uart_clear_interrupt(avr, &p->txc); + avr_uart_clear_interrupt(avr, &p->rxc); avr_irq_register_notify(p->io.irq + UART_IRQ_INPUT, avr_uart_irq_input, p); avr_cycle_timer_cancel(avr, avr_uart_rxc_raise, p); avr_cycle_timer_cancel(avr, avr_uart_txc_raise, p); uart_fifo_reset(&p->input); + p->tx_cnt = 0; - avr_regbit_set(avr, p->ucsz); - avr_regbit_clear(avr, p->ucsz2); + avr_regbit_set(avr, p->ucsz); + avr_uart_regbit_clear(avr, p->ucsz2); // DEBUG allow printf without fiddling with enabling the uart avr_regbit_set(avr, p->txen); - p->usec_per_byte = 100; + p->cycles_per_byte = avr_usec_to_cycles(avr, 100); } static int avr_uart_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param) @@ -288,7 +454,7 @@ void avr_uart_init(avr_t * avr, avr_uart_t * p) // printf("%s UART%c UDR=%02x\n", __FUNCTION__, p->name, p->r_udr); - p->flags = AVR_UART_FLAG_POOL_SLEEP|AVR_UART_FLAG_STDIO; + p->flags = AVR_UART_FLAG_POLL_SLEEP|AVR_UART_FLAG_STDIO; avr_register_io(avr, &p->io); avr_register_vector(avr, &p->rxc); @@ -311,5 +477,6 @@ void avr_uart_init(avr_t * avr, avr_uart_t * p) avr_register_io_write(avr, p->r_ucsra, avr_uart_write, p); if (p->r_ubrrl) avr_register_io_write(avr, p->r_ubrrl, avr_uart_baud_write, p); + avr_register_io_write(avr, p->rxen.reg, avr_uart_write, p); } diff --git a/simavr/sim/avr_uart.h b/simavr/sim/avr_uart.h index 8db33a0..dd3a536 100644 --- a/simavr/sim/avr_uart.h +++ b/simavr/sim/avr_uart.h @@ -76,11 +76,12 @@ enum { #define AVR_IOCTL_UART_GETIRQ(_name) AVR_IOCTL_DEF('u','a','r',(_name)) enum { - // the uart code monitors for firmware that pool on + // the uart code monitors for firmware that poll on // reception registers, and can do an atomic usleep() // if it's detected, this helps regulating CPU AVR_UART_FLAG_POOL_SLEEP = (1 << 0), - AVR_UART_FLAG_STDIO = (1 << 1), // print lines on the console + AVR_UART_FLAG_POLL_SLEEP = (1 << 0), // to replace pool_sleep + AVR_UART_FLAG_STDIO = (1 << 1), // print lines on the console }; typedef struct avr_uart_t { @@ -100,6 +101,12 @@ typedef struct avr_uart_t { avr_regbit_t ucsz; // data bits avr_regbit_t ucsz2; // data bits, continued + // read-only bits (just to mask it out) + avr_regbit_t fe; // frame error bit + avr_regbit_t dor; // data overrun bit + avr_regbit_t upe; // parity error bit + avr_regbit_t rxb8; // receive data bit 8 + avr_io_addr_t r_ubrrl,r_ubrrh; avr_int_vector_t rxc; @@ -107,9 +114,12 @@ typedef struct avr_uart_t { avr_int_vector_t udrc; uart_fifo_t input; + uint8_t tx_cnt; // number of unsent characters in the output buffer + uint32_t rx_cnt; // number of characters read by app since rxc_raise_time uint32_t flags; - avr_cycle_count_t usec_per_byte; + avr_cycle_count_t cycles_per_byte; + avr_cycle_count_t rxc_raise_time; // the cpu cycle when rxc flag was raised last time uint8_t * stdio_out; int stdio_len; // current size in the stdio output @@ -121,6 +131,90 @@ typedef struct avr_uart_t { void avr_uart_init(avr_t * avr, avr_uart_t * port); +#define AVR_UARTX_DECLARE(_name, _prr, _prusart) \ + .uart ## _name = { \ + .name = '0' + _name, \ + .disabled = AVR_IO_REGBIT(_prr, _prusart), \ + \ + .r_udr = UDR ## _name, \ + \ + .fe = AVR_IO_REGBIT(UCSR ## _name ## A, FE ## _name), \ + .dor = AVR_IO_REGBIT(UCSR ## _name ## A, DOR ## _name), \ + .upe = AVR_IO_REGBIT(UCSR ## _name ## A, UPE ## _name), \ + .u2x = AVR_IO_REGBIT(UCSR ## _name ## A, U2X ## _name), \ + .txen = AVR_IO_REGBIT(UCSR ## _name ## B, TXEN ## _name), \ + .rxen = AVR_IO_REGBIT(UCSR ## _name ## B, RXEN ## _name), \ + .rxb8 = AVR_IO_REGBIT(UCSR ## _name ## B, RXB8 ## _name), \ + .usbs = AVR_IO_REGBIT(UCSR ## _name ## C, USBS ## _name), \ + .ucsz = AVR_IO_REGBITS(UCSR ## _name ## C, UCSZ ## _name ## 0, 0x3), \ + .ucsz2 = AVR_IO_REGBIT(UCSR ## _name ## B, UCSZ ## _name ## 2), \ + \ + .r_ucsra = UCSR ## _name ## A, \ + .r_ucsrb = UCSR ## _name ## B, \ + .r_ucsrc = UCSR ## _name ## C, \ + .r_ubrrl = UBRR ## _name ## L, \ + .r_ubrrh = UBRR ## _name ## H, \ + .rxc = { \ + .enable = AVR_IO_REGBIT(UCSR ## _name ## B, RXCIE ## _name), \ + .raised = AVR_IO_REGBIT(UCSR ## _name ## A, RXC ## _name), \ + .vector = USART ## _name ## _RX_vect, \ + .raise_sticky = 1, \ + }, \ + .txc = { \ + .enable = AVR_IO_REGBIT(UCSR ## _name ## B, TXCIE ## _name), \ + .raised = AVR_IO_REGBIT(UCSR ## _name ## A, TXC ## _name), \ + .vector = USART ## _name ## _TX_vect, \ + }, \ + .udrc = { \ + .enable = AVR_IO_REGBIT(UCSR ## _name ## B, UDRIE ## _name), \ + .raised = AVR_IO_REGBIT(UCSR ## _name ## A, UDRE ## _name), \ + .vector = USART ## _name ## _UDRE_vect, \ + .raise_sticky = 1, \ + }, \ + } + +// This macro is for older single-interface devices where variable names are bit divergent +#define AVR_UART_DECLARE(_prr, _prusart, _upe_name, _rname_ix, _intr_c) \ + .uart = { \ + .name = '0', \ + .disabled = AVR_IO_REGBIT(_prr, _prusart), \ + .r_udr = UDR ## _rname_ix, \ + \ + .fe = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, FE ## _rname_ix), \ + .dor = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, DOR ## _rname_ix), \ + .upe = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, _upe_name ## _rname_ix), \ + .u2x = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, U2X ## _rname_ix), \ + .txen = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, TXEN ## _rname_ix), \ + .rxen = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, RXEN ## _rname_ix), \ + .rxb8 = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, RXB8 ## _rname_ix), \ + .usbs = AVR_IO_REGBIT(UCSR ## _rname_ix ## C, USBS ## _rname_ix), \ + .ucsz = AVR_IO_REGBITS(UCSR ## _rname_ix ## C, UCSZ ## _rname_ix ## 0, 0x3), \ + .ucsz2 = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, UCSZ ## _rname_ix ## 2), \ + \ + .r_ucsra = UCSR ## _rname_ix ## A, \ + .r_ucsrb = UCSR ## _rname_ix ## B, \ + .r_ucsrc = UCSR ## _rname_ix ## C, \ + .r_ubrrl = UBRR ## _rname_ix ## L, \ + .r_ubrrh = UBRR ## _rname_ix ## H, \ + .rxc = { \ + .enable = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, RXCIE ## _rname_ix), \ + .raised = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, RXC ## _rname_ix), \ + .vector = USART_RX ## _intr_c ## _vect, \ + .raise_sticky = 1, \ + }, \ + .txc = { \ + .enable = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, TXCIE ## _rname_ix), \ + .raised = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, TXC ## _rname_ix), \ + .vector = USART_TX ## _intr_c ## _vect, \ + }, \ + .udrc = { \ + .enable = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, UDRIE ## _rname_ix), \ + .raised = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, UDRE ## _rname_ix), \ + .vector = USART_UDRE_vect, \ + .raise_sticky = 1, \ + }, \ + } + #ifdef __cplusplus }; #endif -- 2.39.5