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