3 This file is part of the OpenARMWare.
4 Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
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.
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.
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/>.
23 #include "hw_uart_regs.h"
24 #include "uart_defines.h"
25 #include "circularbytebuffer.h"
29 uint32_t uart_base[] = { UART0_BASE, UART1_BASE, UART2_BASE };
32 uint32_t gpio_base[] =
33 { GPIOA_BASE, GPIOB_BASE, GPIOC_BASE, GPIOD_BASE,
34 GPIOE_BASE, GPIOF_BASE, GPIOG_BASE, GPIOH_BASE,
39 uint8_t uart_tx_gpio[] = { GPIOA, GPIOD, GPIOG };
41 uint8_t uart_rx_gpio[] = { GPIOA, GPIOD, GPIOG };
43 uint8_t uart_tx_pin[] = { 1, 1, 1 };
45 uint8_t uart_rx_pin[] = { 0, 0, 0 };
47 uint8_t uart_tx_pctl[] = {1, 5, 1};
49 uint8_t uart_rx_pctl[] = {1, 5, 1};
51 uint8_t uart_isr_vector[] = {5, 6, 33};
54 uint32_t uart_rx_buffersize[] = {128, 128, 128};
56 uint32_t uart_tx_buffersize[] = {256, 256, 256};
59 circularbytebuffer_t uart_rx_buffer[3];
61 circularbytebuffer_t uart_tx_buffer[3];
65 void uart_tx_isr(uint8_t uartno);
67 void uart_rx_isr(uint8_t uartno);
71 if(HW_REG(UART0_BASE+UARTMIS_OFFSET)&_BV(UART_TXMIS)){
72 // HW_REG(uart_base[0]+UARTDR_OFFSET) = 'X';
75 if(HW_REG(UART0_BASE+UARTMIS_OFFSET)&_BV(UART_RXMIS)){
81 void uart_tx_isr(uint8_t uartno){
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]));
88 HW_REG(uart_base[uartno]+UARTICR_OFFSET) |= _BV(UART_TXIC);
92 void uart_rx_isr(uint8_t uartno){
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]));
98 HW_REG(uart_base[uartno]+UARTICR_OFFSET) |= _BV(UART_RXIC);
101 void calc_baud_values(uint32_t baudrate, uint16_t* intdivider, uint8_t* fracdivider, uint8_t* highspeed){
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));
114 *fracdivider = (uint8_t)(tmp&0x3f);
115 *intdivider = (uint16_t)(tmp>>6);
118 uint8_t uart_init(uint8_t uartno, uint32_t baudrate, uint8_t databits, uint8_t paraty, uint8_t stopbits){
124 return UART_ERROR_WRONG_UART;
126 if(databits>UART_DATABITS_8){
127 return UART_ERROR_WRONG_DATABITS;
129 if(paraty>UART_PARATY_SPACE){
130 return UART_ERROR_WRONG_PARATY;
132 if(stopbits>UART_STOPBITS_TWO){
133 return UART_ERROR_WRONG_STOPBITS;
135 if(0==circularbytebuffer_init(uart_rx_buffersize[uartno], &(uart_rx_buffer[uartno]))){
136 return UART_ERROR_RX_BUFFER_INIT;
138 if(0==circularbytebuffer_init(uart_tx_buffersize[uartno], &(uart_tx_buffer[uartno]))){
139 return UART_ERROR_TX_BUFFER_INIT;
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)
145 HW_REG(SYSCTL_BASE+RCGC2_OFFSET) |= 1;
146 for(tmp=0; tmp<100; ++tmp)
148 /* enable clock for uart */
149 HW_REG(SYSCTL_BASE+RCGC1_OFFSET) |= _BV(uartno);
150 for(tmp=0; tmp<100; ++tmp)
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 */
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)
181 HW_REG(uart_base[uartno]+UARTCTL_OFFSET) &= ~_BV(UART_UARTEN);
182 /* set baudrate parameters */
183 uint8_t highspeed, fbrd;
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))
195 HW_REG(uart_base[uartno]+UARTLCRH_OFFSET) &= ~_BV(UART_FEN);
197 /* set line parameters (bits, paraty, stopbits*/
198 tmp = HW_REG(uart_base[uartno]+UARTLCRH_OFFSET);
200 tmp |= (paraty==UART_PARATY_MARK||paraty==UART_PARATY_SPACE)?_BV(7):0; /* set flag for mark or space paraty*/
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 */
209 HW_REG(uart_base[uartno]+UARTCTL_OFFSET) |= _BV(UART_HSE);
211 HW_REG(uart_base[uartno]+UARTCTL_OFFSET) &= ~_BV(UART_HSE);
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);
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);
223 return UART_ERROR_OK;
227 void uart_putc(uint8_t uartno, uint8_t byte){
231 /* wait while buffer is full */
232 while(circularbytebuffer_cnt(&(uart_tx_buffer[uartno]))==uart_tx_buffersize[uartno]){
234 if(circularbytebuffer_cnt(&(uart_tx_buffer[uartno]))>0){
235 circularbytebuffer_append(byte, &(uart_tx_buffer[uartno]));
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]));
243 HW_REG(uart_base[uartno]+UARTDR_OFFSET) = (uint32_t)byte;
246 uint16_t uart_getc(uint8_t uartno){
250 if(circularbytebuffer_cnt(&(uart_rx_buffer[uartno]))){
251 return circularbytebuffer_get_fifo(&(uart_rx_buffer[uartno]));
253 /* wait while the FIFO is empty */
254 while(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_RXFE))
256 return (uint16_t)HW_REG(uart_base[uartno]+UARTDR_OFFSET);
259 uint32_t uart_dataavail(uint8_t uartno){
263 /* wait while the FIFO is empty */
264 if(circularbytebuffer_cnt(&(uart_rx_buffer[uartno]))){
267 return(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_RXFE))?0:1;