]> git.cryptolib.org Git - arm-crypto-lib.git/blob - test_src/uart_i.c
switching to dedicated endian switching function
[arm-crypto-lib.git] / test_src / uart_i.c
1 /* uart_i.c */
2 /*
3     This file is part of the OpenARMWare.
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 #include "circularbytebuffer.h"
26
27
28 static const
29 uint32_t uart_base[] = { UART0_BASE, UART1_BASE, UART2_BASE };
30
31 static const
32 uint32_t gpio_base[] =
33         { GPIOA_BASE, GPIOB_BASE, GPIOC_BASE, GPIOD_BASE,
34           GPIOE_BASE, GPIOF_BASE, GPIOG_BASE, GPIOH_BASE,
35           GPIOJ_BASE,
36         };
37
38 static const
39 uint8_t uart_tx_gpio[] = { GPIOA, GPIOD, GPIOG };
40 static const
41 uint8_t uart_rx_gpio[] = { GPIOA, GPIOD, GPIOG };
42 static const
43 uint8_t uart_tx_pin[] = { 1, 1, 1 };
44 static const
45 uint8_t uart_rx_pin[] = { 0, 0, 0 };
46 static const
47 uint8_t uart_tx_pctl[] = {1, 5, 1};
48 static const
49 uint8_t uart_rx_pctl[] = {1, 5, 1};
50 static const
51 uint8_t uart_isr_vector[] = {5, 6, 33};
52
53 static const
54 uint32_t uart_rx_buffersize[] = {128, 128, 128};
55 static const
56 uint32_t uart_tx_buffersize[] = {256, 256, 256};
57
58 static
59 circularbytebuffer_t uart_rx_buffer[3];
60 static
61 circularbytebuffer_t uart_tx_buffer[3];
62
63
64 static
65 void uart_tx_isr(uint8_t uartno);
66 static
67 void uart_rx_isr(uint8_t uartno);
68
69 void uart0_isr(void){
70
71         if(HW_REG(UART0_BASE+UARTMIS_OFFSET)&_BV(UART_TXMIS)){
72 //              HW_REG(uart_base[0]+UARTDR_OFFSET) = 'X';
73                 uart_tx_isr(UART_0);
74         }
75         if(HW_REG(UART0_BASE+UARTMIS_OFFSET)&_BV(UART_RXMIS)){
76                 uart_rx_isr(UART_0);
77         }
78 }
79
80 static
81 void uart_tx_isr(uint8_t uartno){
82         uint32_t tmp;
83         tmp = circularbytebuffer_cnt(&(uart_tx_buffer[uartno]));
84         while(tmp-- && (!(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_TXFF)))){
85                 HW_REG(uart_base[uartno]+UARTDR_OFFSET)
86                                 = (uint32_t)circularbytebuffer_get_fifo(&(uart_tx_buffer[uartno]));
87         }
88         HW_REG(uart_base[uartno]+UARTICR_OFFSET) |= _BV(UART_TXIC);
89 }
90
91 static
92 void uart_rx_isr(uint8_t uartno){
93         uint8_t c;
94         while(!(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_RXFE))){
95                 c = HW_REG(uart_base[uartno]+UARTDR_OFFSET);
96                 circularbytebuffer_append(c, &(uart_rx_buffer[uartno]));
97         }
98         HW_REG(uart_base[uartno]+UARTICR_OFFSET) |= _BV(UART_RXIC);
99 }
100
101 void calc_baud_values(uint32_t baudrate, uint16_t* intdivider, uint8_t* fracdivider, uint8_t* highspeed){
102         uint32_t tmp;
103         uint32_t uart_freq;
104         if(baudrate==0){
105                 return;
106         }
107         uart_freq = sysclk_get_freq();
108         *highspeed = ((baudrate*16L)>uart_freq)?1:0;
109 //      tmp = (((uint64_t)UART_FREQ)*128LL)/(((*highspeed)?8L:16L)*baudrate);
110         tmp = uart_freq<<((*highspeed)?(7-3):(7-4));
111         tmp /= baudrate;
112         tmp++;
113         tmp>>=1;
114         *fracdivider = (uint8_t)(tmp&0x3f);
115         *intdivider = (uint16_t)(tmp>>6);
116 }
117
118 uint8_t uart_init(uint8_t uartno, uint32_t baudrate, uint8_t databits, uint8_t paraty, uint8_t stopbits){
119         uint32_t tmp;
120         if(databits>=5){
121                 databits-=5;
122         }
123         if(uartno>UART_MAX){
124                 return UART_ERROR_WRONG_UART;
125         }
126         if(databits>UART_DATABITS_8){
127                 return UART_ERROR_WRONG_DATABITS;
128         }
129         if(paraty>UART_PARATY_SPACE){
130                 return UART_ERROR_WRONG_PARATY;
131         }
132         if(stopbits>UART_STOPBITS_TWO){
133                 return UART_ERROR_WRONG_STOPBITS;
134         }
135         if(0==circularbytebuffer_init(uart_rx_buffersize[uartno], &(uart_rx_buffer[uartno]))){
136                 return UART_ERROR_RX_BUFFER_INIT;
137         }
138         if(0==circularbytebuffer_init(uart_tx_buffersize[uartno], &(uart_tx_buffer[uartno]))){
139                 return UART_ERROR_TX_BUFFER_INIT;
140         }
141         /* enable clock for gpio*/
142         HW_REG(SYSCTL_BASE+RCGC2_OFFSET) |= _BV(uart_rx_gpio[uartno]) | _BV(uart_tx_gpio[uartno]);
143     for(tmp=0; tmp<100; ++tmp)
144         ;
145     HW_REG(SYSCTL_BASE+RCGC2_OFFSET) |= 1;
146     for(tmp=0; tmp<100; ++tmp)
147         ;
148         /* enable clock for uart */
149         HW_REG(SYSCTL_BASE+RCGC1_OFFSET) |= _BV(uartno);
150     for(tmp=0; tmp<100; ++tmp)
151         ;
152     HW_REG(gpio_base[uart_rx_gpio[uartno]] + GPIO_ODR_OFFSET) &= ~_BV(uart_rx_pin[uartno]); /* open drain */
153     HW_REG(gpio_base[uart_tx_gpio[uartno]] + GPIO_ODR_OFFSET) &= ~_BV(uart_tx_pin[uartno]); /* open drain */
154     HW_REG(gpio_base[uart_rx_gpio[uartno]] + GPIO_PUR_OFFSET) &= ~_BV(uart_rx_pin[uartno]); /* pull-up */
155     HW_REG(gpio_base[uart_tx_gpio[uartno]] + GPIO_PUR_OFFSET) &= ~_BV(uart_tx_pin[uartno]); /* pull-up */
156     HW_REG(gpio_base[uart_rx_gpio[uartno]] + GPIO_PDR_OFFSET) &= ~_BV(uart_rx_pin[uartno]); /* pull-down*/
157     HW_REG(gpio_base[uart_tx_gpio[uartno]] + GPIO_PDR_OFFSET) &= ~_BV(uart_tx_pin[uartno]); /* pull-down*/
158     HW_REG(gpio_base[uart_rx_gpio[uartno]] + GPIO_DEN_OFFSET) |=  _BV(uart_rx_pin[uartno]); /* digital enable */
159     HW_REG(gpio_base[uart_tx_gpio[uartno]] + GPIO_DEN_OFFSET) |=  _BV(uart_tx_pin[uartno]); /* digital enable */
160
161         /* switch to alternate function for rx */
162         HW_REG(gpio_base[uart_rx_gpio[uartno]]+GPIO_AFSEL_OFFSET) |= _BV(uart_rx_pin[uartno]);
163          /* switch to alternate function for tx */
164         HW_REG(gpio_base[uart_tx_gpio[uartno]]+GPIO_AFSEL_OFFSET) |= _BV(uart_tx_pin[uartno]);
165         /* switch multiplexer to uart for rx */
166         HW_REG(gpio_base[uart_rx_gpio[uartno]]+GPIO_PCTL_OFFSET) &= ~(0x0f<<(uart_rx_pin[uartno]*4));
167         HW_REG(gpio_base[uart_rx_gpio[uartno]]+GPIO_PCTL_OFFSET) |= ((uart_rx_pctl[uartno])<<(uart_rx_pin[uartno]*4));
168         /* switch multiplexer to uart for tx */
169         HW_REG(gpio_base[uart_tx_gpio[uartno]]+GPIO_PCTL_OFFSET) &= ~(0x0f<<(uart_tx_pin[uartno]*4));
170         HW_REG(gpio_base[uart_tx_gpio[uartno]]+GPIO_PCTL_OFFSET) |= ((uart_tx_pctl[uartno])<<(uart_tx_pin[uartno]*4));
171         /* set pins to be 2mA */
172         HW_REG(gpio_base[uart_rx_gpio[uartno]]+GPIO_DR2R_OFFSET) |= _BV(uart_rx_pin[uartno]);
173         HW_REG(gpio_base[uart_tx_gpio[uartno]]+GPIO_DR2R_OFFSET) |= _BV(uart_tx_pin[uartno]);
174         /* configure rx pin as input */
175         HW_REG(gpio_base[uart_rx_gpio[uartno]]+GPIO_DIR_OFFSET) &= ~_BV(uart_rx_pin[uartno]);
176         /* configure tx pin as output */
177         HW_REG(gpio_base[uart_tx_gpio[uartno]]+GPIO_DIR_OFFSET) |= _BV(uart_tx_pin[uartno]);
178     for(tmp=0; tmp<100; ++tmp)
179         ;
180         /* disable uart */
181         HW_REG(uart_base[uartno]+UARTCTL_OFFSET) &= ~_BV(UART_UARTEN);
182         /* set baudrate parameters */
183         uint8_t highspeed, fbrd;
184         uint16_t ibrd;
185         calc_baud_values(baudrate, &ibrd, &fbrd, &highspeed);
186         tmp=HW_REG(uart_base[uartno]+UARTLCRH_OFFSET);
187         HW16_REG(uart_base[uartno]+UARTIBRD_OFFSET) = ibrd;
188     HW8_REG(uart_base[uartno]+UARTFBRD_OFFSET) = fbrd;
189     HW_REG(uart_base[uartno]+UARTLCRH_OFFSET) = tmp;
190         /* wait until uart is no longer busy */
191         while(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_BUSY))
192                 ;
193
194         /* flush FIFOs */
195         HW_REG(uart_base[uartno]+UARTLCRH_OFFSET) &= ~_BV(UART_FEN);
196
197         /* set line parameters (bits, paraty, stopbits*/
198         tmp = HW_REG(uart_base[uartno]+UARTLCRH_OFFSET);
199         tmp &= ~0xff;
200         tmp |= (paraty==UART_PARATY_MARK||paraty==UART_PARATY_SPACE)?_BV(7):0; /* set flag for mark or space paraty*/
201         tmp |= databits<<5;
202         tmp |= _BV(UART_FEN); /* enable FIFOs */
203         tmp |= (stopbits==UART_STOPBITS_TWO)?_BV(3):0;
204         tmp |= (paraty==UART_PARATY_EVEN || paraty==UART_PARATY_MARK)?_BV(2):0;
205         tmp |= (paraty!=UART_PARATY_NONE)?_BV(1):0;
206         HW_REG(uart_base[uartno]+UARTLCRH_OFFSET) = tmp;
207         /* set the highspeed bit accordingly */
208         if(highspeed){
209                 HW_REG(uart_base[uartno]+UARTCTL_OFFSET) |= _BV(UART_HSE);
210         } else {
211                 HW_REG(uart_base[uartno]+UARTCTL_OFFSET) &= ~_BV(UART_HSE);
212         }
213         /* uart interrupt enable */
214         HW_REG(uart_base[uartno]+UARTIM_OFFSET) |= _BV(UART_TXIM) | _BV(UART_RXIM);
215         HW_REG(ISR_ENABLE_VECTOR+4*(uart_isr_vector[uartno]/32)) |=
216                         _BV(uart_isr_vector[uartno]%32);
217
218         HW_REG(uart_base[uartno]+UARTCTL_OFFSET) |= _BV(UART_EOT);
219         HW_REG(uart_base[uartno]+UARTFR_OFFSET) = 0;
220         HW_REG(uart_base[uartno]+UARTCTL_OFFSET) |= _BV(UART_RXE) | _BV(UART_TXE);
221         HW_REG(uart_base[uartno]+UARTCTL_OFFSET) |= _BV(UART_UARTEN);
222
223         return UART_ERROR_OK;
224 }
225
226
227 void uart_putc(uint8_t uartno, uint8_t byte){
228         if(uartno>UART_MAX){
229                 return;
230         }
231         /* wait while buffer is full */
232         while(circularbytebuffer_cnt(&(uart_tx_buffer[uartno]))==uart_tx_buffersize[uartno]){
233         }
234         if(circularbytebuffer_cnt(&(uart_tx_buffer[uartno]))>0){
235                 circularbytebuffer_append(byte, &(uart_tx_buffer[uartno]));
236                 return;
237         }
238         /* if we have a full uart, append to buffer */
239         if(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_TXFF)){
240                 circularbytebuffer_append(byte, &(uart_tx_buffer[uartno]));
241                 return;
242         }
243         HW_REG(uart_base[uartno]+UARTDR_OFFSET) = (uint32_t)byte;
244 }
245
246 uint16_t uart_getc(uint8_t uartno){
247         if(uartno>UART_MAX){
248                 return 0xffff;
249         }
250         if(circularbytebuffer_cnt(&(uart_rx_buffer[uartno]))){
251                 return circularbytebuffer_get_fifo(&(uart_rx_buffer[uartno]));
252         }
253         /* wait while the FIFO is empty */
254         while(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_RXFE))
255                 ;
256         return (uint16_t)HW_REG(uart_base[uartno]+UARTDR_OFFSET);
257 }
258
259 uint32_t uart_dataavail(uint8_t uartno){
260         if(uartno>UART_MAX){
261                 return 0;
262         }
263         /* wait while the FIFO is empty */
264         if(circularbytebuffer_cnt(&(uart_rx_buffer[uartno]))){
265                 return 1;
266         }
267         return(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_RXFE))?0:1;
268 }
269
270
271 void uart_flush(uint8_t uartno){
272         if(uartno>UART_MAX){
273                 return;
274         }
275         while(circularbytebuffer_cnt(&(uart_tx_buffer[uartno])))
276                 ;
277         while((HW_REG(uart_base[uartno]+UARTCTL_OFFSET)&_BV(UART_EOT)) == 0)
278                 ;
279 }