Fixes #104, #193 and others.
},
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),
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),
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),
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),
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),
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),
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),
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),
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),
.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,
.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),
.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) },
#include <stdio.h>
#include "avr_lin.h"
+#include "sim_time.h"
static void
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
#include <stdlib.h>
#include "avr_uart.h"
#include "sim_hex.h"
+#include "sim_time.h"
+#include "sim_gdb.h"
//#define TRACE(_w) _w
#ifndef TRACE
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;
}
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);
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;
}
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;
}
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
+ }
}
{
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);
+ }
}
}
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!!" : "");)
{
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)
// 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);
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);
}
#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 {
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;
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
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