]> git.cryptolib.org Git - arm-crypto-lib.git/blob - test_src/uart_lowlevel.c
including even/odd-trick for BMW
[arm-crypto-lib.git] / test_src / uart_lowlevel.c
1 /* uart_lowlevel.c */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <stdint.h>
21 #include "sysclock.h"
22 #include "hw_regs.h"
23 #include "hw_uart_regs.h"
24 #include "uart_defines.h"
25
26 void calc_baud_values(uint32_t baudrate, uint16_t* intdivider, uint8_t* fracdivider, uint8_t* highspeed){
27         uint32_t tmp;
28         uint32_t uart_freq;
29         uart_freq = sysclk_get_freq();
30         *highspeed = (baudrate*16>uart_freq)?1:0;
31         tmp = (uint64_t)uart_freq*128/((*highspeed?8:16)*baudrate);
32         tmp++;
33         tmp>>=1;
34         *fracdivider = (uint8_t)(tmp&0x3f);
35         *intdivider = tmp>>6;
36 }
37
38 static const
39 uint32_t uart_base[] = { UART0_BASE, UART1_BASE, UART2_BASE };
40
41 static const
42 uint32_t gpio_base[] =
43         { GPIOA_BASE, GPIOB_BASE, GPIOC_BASE, GPIOD_BASE,
44           GPIOE_BASE, GPIOF_BASE, GPIOG_BASE, GPIOH_BASE,
45           GPIOJ_BASE,
46         };
47
48 static const
49 uint8_t uart_tx_gpio[] = { GPIOA, GPIOD, GPIOG };
50 static const
51 uint8_t uart_rx_gpio[] = { GPIOA, GPIOD, GPIOG };
52 static const
53 uint8_t uart_tx_pin[] = { 1, 1, 1 };
54 static const
55 uint8_t uart_rx_pin[] = { 0, 0, 0 };
56 static const
57 uint8_t uart_tx_pctl[] = {1, 5, 1};
58 static const
59 uint8_t uart_rx_pctl[] = {1, 5, 1};
60
61 uint8_t uart_init(uint8_t uartno, uint32_t baudrate, uint8_t databits, uint8_t paraty, uint8_t stopbits){
62         uint32_t tmp;
63         if(databits>=5){
64                 databits-=5;
65         }
66         if(uartno>UART_MAX){
67                 return UART_ERROR_WRONG_UART;
68         }
69         if(databits>UART_DATABITS_8){
70                 return UART_ERROR_WRONG_DATABITS;
71         }
72         if(paraty>UART_PARATY_SPACE){
73                 return UART_ERROR_WRONG_PARATY;
74         }
75         if(stopbits>UART_STOPBITS_TWO){
76                 return UART_ERROR_WRONG_STOPBITS;
77         }
78         /* enable clock for uart */
79         HW_REG(SYSCTL_BASE+RCGC1_OFFSET) |= _BV(uartno);
80         /* enable clock for gpio*/
81         HW_REG(SYSCTL_BASE+RCGC2_OFFSET) |= _BV(uart_rx_gpio[uartno]) | _BV(uart_tx_gpio[uartno]);
82     HW_REG(SYSCTL_BASE+RCGC2_OFFSET) |= 1;
83
84     HW_REG(gpio_base[uart_rx_gpio[uartno]] + GPIO_ODR_OFFSET) &= ~_BV(uart_rx_pin[uartno]); /* open drain */
85     HW_REG(gpio_base[uart_tx_gpio[uartno]] + GPIO_ODR_OFFSET) &= ~_BV(uart_tx_pin[uartno]); /* open drain */
86     HW_REG(gpio_base[uart_rx_gpio[uartno]] + GPIO_PUR_OFFSET) &= ~_BV(uart_rx_pin[uartno]); /* pull-up */
87     HW_REG(gpio_base[uart_tx_gpio[uartno]] + GPIO_PUR_OFFSET) &= ~_BV(uart_tx_pin[uartno]); /* pull-up */
88     HW_REG(gpio_base[uart_rx_gpio[uartno]] + GPIO_PDR_OFFSET) &= ~_BV(uart_rx_pin[uartno]); /* pull-down*/
89     HW_REG(gpio_base[uart_tx_gpio[uartno]] + GPIO_PDR_OFFSET) &= ~_BV(uart_tx_pin[uartno]); /* pull-down*/
90     HW_REG(gpio_base[uart_rx_gpio[uartno]] + GPIO_DEN_OFFSET) |=  _BV(uart_rx_pin[uartno]); /* digital enable */
91     HW_REG(gpio_base[uart_tx_gpio[uartno]] + GPIO_DEN_OFFSET) |=  _BV(uart_tx_pin[uartno]); /* digital enable */
92
93         /* switch to alternate function for rx */
94         HW_REG(gpio_base[uart_rx_gpio[uartno]]+GPIO_AFSEL_OFFSET) |= _BV(uart_rx_pin[uartno]);
95          /* switch to alternate function for tx */
96         HW_REG(gpio_base[uart_tx_gpio[uartno]]+GPIO_AFSEL_OFFSET) |= _BV(uart_tx_pin[uartno]);
97         /* switch multiplexer to uart for rx */
98         HW_REG(gpio_base[uart_rx_gpio[uartno]]+GPIO_PCTL_OFFSET) &= ~(0x0f<<(uart_rx_pin[uartno]*4));
99         HW_REG(gpio_base[uart_rx_gpio[uartno]]+GPIO_PCTL_OFFSET) |= ((uart_rx_pctl[uartno])<<(uart_rx_pin[uartno]*4));
100         /* switch multiplexer to uart for tx */
101         HW_REG(gpio_base[uart_tx_gpio[uartno]]+GPIO_PCTL_OFFSET) &= ~(0x0f<<(uart_tx_pin[uartno]*4));
102         HW_REG(gpio_base[uart_tx_gpio[uartno]]+GPIO_PCTL_OFFSET) |= ((uart_tx_pctl[uartno])<<(uart_tx_pin[uartno]*4));
103         /* set pins to be 2mA */
104         HW_REG(gpio_base[uart_rx_gpio[uartno]]+GPIO_DR2R_OFFSET) |= _BV(uart_rx_pin[uartno]);
105         HW_REG(gpio_base[uart_tx_gpio[uartno]]+GPIO_DR2R_OFFSET) |= _BV(uart_tx_pin[uartno]);
106         /* configure rx pin as input */
107         HW_REG(gpio_base[uart_rx_gpio[uartno]]+GPIO_DIR_OFFSET) &= ~_BV(uart_rx_pin[uartno]);
108         /* configure tx pin as output */
109         HW_REG(gpio_base[uart_tx_gpio[uartno]]+GPIO_DIR_OFFSET) |= _BV(uart_tx_pin[uartno]);
110
111         /* disable uart */
112         HW_REG(uart_base[uartno]+UARTCTL_OFFSET) &= ~_BV(UARTEN);
113         /* set baudrate parameters */
114         uint8_t highspeed;
115         calc_baud_values(baudrate,
116                                  (uint16_t*)&HW_REG(uart_base[uartno]+UARTIBRD_OFFSET),
117                                  (uint8_t*)&HW_REG(uart_base[uartno]+UARTFBRD_OFFSET),
118                                  &highspeed);
119         /* wait until uart is no longer busy */
120         while(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_BUSY))
121                 ;
122         /* flush FIFOs */
123         HW_REG(uart_base[uartno]+UARTLCRH_OFFSET) &= ~_BV(UART_FEN);
124         /* set line parameters (bits, paraty, stopbits*/
125         tmp = HW_REG(uart_base[uartno]+UARTLCRH_OFFSET);
126         tmp &= ~0xff;
127         tmp |= (paraty==UART_PARATY_MARK||paraty==UART_PARATY_SPACE)?_BV(7):0; /* set flag for mark or space paraty*/
128         tmp |= databits<<5;
129         tmp |= _BV(UART_FEN); /* enable FIFOs */
130         tmp |= (stopbits==UART_STOPBITS_TWO)?_BV(3):0;
131         tmp |= (paraty==UART_PARATY_EVEN || paraty==UART_PARATY_MARK)?_BV(2):0;
132         tmp |= (paraty!=UART_PARATY_NONE)?_BV(1):0;
133         HW_REG(uart_base[uartno]+UARTLCRH_OFFSET) = tmp;
134         /* set the highspeed bit accordingly */
135         if(highspeed){
136                 HW_REG(uart_base[uartno]+UARTCTL_OFFSET) |= _BV(UART_HSE);
137         } else {
138                 HW_REG(uart_base[uartno]+UARTCTL_OFFSET) &= ~_BV(UART_HSE);
139         }
140         HW_REG(uart_base[uartno]+UARTFR_OFFSET) = 0;
141         HW_REG(uart_base[uartno]+UARTCTL_OFFSET) |= _BV(UART_RXE) | _BV(UART_TXE);
142         HW_REG(uart_base[uartno]+UARTCTL_OFFSET) |= _BV(UARTEN);
143
144         return UART_ERROR_OK;
145 }
146
147
148 void uart_putc(uint8_t uartno, uint8_t byte){
149         if(uartno>UART_MAX){
150                 return;
151         }
152         /* wait while the FIFO is full */
153         while(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_TXFF))
154                 ;
155         HW_REG(uart_base[uartno]+UARTDR_OFFSET) = (uint32_t)byte;
156 }
157
158 uint16_t uart_getc(uint8_t uartno){
159         if(uartno>UART_MAX){
160                 return 0xffff;
161         }
162         /* wait while the FIFO is empty */
163         while(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_RXFE))
164                 ;
165         return (uint16_t)HW_REG(uart_base[uartno]+UARTDR_OFFSET);
166 }
167
168 uint32_t uart_dataavail(uint8_t uartno){
169         if(uartno>UART_MAX){
170                 return 0;
171         }
172         /* wait while the FIFO is empty */
173         return(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_RXFE))?0:1;
174 }