00001
00038 #include <cfg/macros.h>
00039 #include <drv/gpio_lm3s.h>
00040 #include <drv/ser_p.h>
00041 #include <drv/ser.h>
00042 #include <drv/irq_cm3.h>
00043 #include "cfg/cfg_ser.h"
00044 #include "ser_lm3s.h"
00045
00046
00047 extern struct Serial *ser_handles[SER_CNT];
00048
00049 struct CM3Serial
00050 {
00051 struct SerialHardware hw;
00052 bool sending;
00053 uint32_t base;
00054 sysirq_t irq;
00055 };
00056
00057
00058 static struct CM3Serial UARTDesc[SER_CNT];
00059
00060
00061 struct gpio_uart_info
00062 {
00063
00064 uint32_t sysctl;
00065
00066 uint32_t base;
00067
00068 uint8_t pins;
00069 };
00070
00071
00072 static const struct gpio_uart_info gpio_uart[SER_CNT] =
00073 {
00074
00075 {
00076 .base = GPIO_PORTA_BASE,
00077 .pins = BV(1) | BV(0),
00078 .sysctl = SYSCTL_RCGC2_GPIOA,
00079 },
00080
00081 {
00082 .base = GPIO_PORTD_BASE,
00083 .pins = BV(3) | BV(2),
00084 .sysctl = SYSCTL_RCGC2_GPIOD,
00085 },
00086
00087 {
00088 .base = GPIO_PORTG_BASE,
00089 .pins = BV(1) | BV(0),
00090 .sysctl = SYSCTL_RCGC2_GPIOG,
00091 },
00092 };
00093
00094 void lm3s_uartSetBaudRate(uint32_t base, unsigned long baud)
00095 {
00096 unsigned long div;
00097 bool hi_speed;
00098
00099 if (baud * 16 > CPU_FREQ)
00100 {
00101 hi_speed = true;
00102 baud /= 2;
00103 }
00104 div = (CPU_FREQ * 8 / baud + 1) / 2;
00105
00106 lm3s_uartDisable(base);
00107 if (hi_speed)
00108 HWREG(base + UART_O_CTL) |= UART_CTL_HSE;
00109 else
00110 HWREG(base + UART_O_CTL) &= ~UART_CTL_HSE;
00111
00112 HWREG(base + UART_O_IBRD) = div / 64;
00113 HWREG(base + UART_O_FBRD) = div % 64;
00114 lm3s_uartClear(base);
00115 lm3s_uartEnable(base);
00116 }
00117
00118 void lm3s_uartSetParity(uint32_t base, int parity)
00119 {
00120
00121 uint32_t config = UART_LCRH_WLEN_8;
00122
00123 switch(parity)
00124 {
00125 case SER_PARITY_NONE:
00126 break;
00127 case SER_PARITY_ODD:
00128 config |= UART_LCRH_PEN;
00129 break;
00130 case SER_PARITY_EVEN:
00131 config |= UART_LCRH_EPS | UART_LCRH_PEN;
00132 break;
00133 default:
00134 ASSERT(0);
00135 return;
00136 }
00137 lm3s_uartDisable(base);
00138 HWREG(base + UART_O_LCRH) = config;
00139 lm3s_uartClear(base);
00140 lm3s_uartEnable(base);
00141 }
00142
00143 void lm3s_uartInit(int port)
00144 {
00145 uint32_t reg_clock, base;
00146
00147 ASSERT(port >= 0 && port < SER_CNT);
00148
00149 base = UARTDesc[port].base;
00150 reg_clock = 1 << port;
00151
00152
00153 SYSCTL_RCGC1_R |= reg_clock;
00154 SYSCTL_RCGC2_R |= gpio_uart[port].sysctl;
00155 lm3s_busyWait(512);
00156
00157
00158 lm3s_gpioPinConfig(gpio_uart[port].base, gpio_uart[port].pins,
00159 GPIO_DIR_MODE_HW, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
00160
00161
00162 lm3s_uartSetBaudRate(base, 115200);
00163 lm3s_uartSetParity(base, SER_PARITY_NONE);
00164 }
00165
00166 static bool tx_sending(struct SerialHardware *_hw)
00167 {
00168 struct CM3Serial *hw = (struct CM3Serial *)_hw;
00169 return hw->sending;
00170 }
00171
00172 static void uart_irq_rx(int port)
00173 {
00174 struct FIFOBuffer *rxfifo = &ser_handles[port]->rxfifo;
00175 uint32_t base = UARTDesc[port].base;
00176 char c;
00177
00178 while (lm3s_uartRxReady(base))
00179 {
00180 c = HWREG(base + UART_O_DR);
00181 if (fifo_isfull(rxfifo))
00182 ser_handles[port]->status |= SERRF_RXFIFOOVERRUN;
00183 else
00184 fifo_push(rxfifo, c);
00185 }
00186 }
00187
00188 static void uart_irq_tx(int port)
00189 {
00190 struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo;
00191 uint32_t base = UARTDesc[port].base;
00192
00193 while (lm3s_uartTxReady(base))
00194 {
00195 if (fifo_isempty(txfifo)) {
00196
00197
00198
00199
00200 HWREG(base + UART_O_IM) &= ~UART_IM_TXIM;
00201 UARTDesc[port].sending = false;
00202 break;
00203 }
00204 HWREG(base + UART_O_DR) = fifo_pop(txfifo);
00205 }
00206 }
00207
00208 static void uart_common_irq_handler(int port)
00209 {
00210 uint32_t base = UARTDesc[port].base;
00211 uint32_t status;
00212
00213
00214 status = HWREG(base + UART_O_RIS);
00215
00216
00217 if (status & (UART_RIS_RXRIS | UART_RIS_RTRIS))
00218 uart_irq_rx(port);
00219 if (status & UART_RIS_TXRIS)
00220 uart_irq_tx(port);
00221 }
00222
00223 static void
00224 lm3s_uartIRQEnable(int port, sysirq_handler_t handler)
00225 {
00226 uint32_t base = UARTDesc[port].base;
00227 sysirq_t irq = UARTDesc[port].irq;
00228
00229
00230 sysirq_setHandler(irq, handler);
00231
00232 HWREG(base + UART_O_IM) |= UART_IM_RXIM | UART_IM_RTIM;
00233 }
00234
00235 static void lm3s_uartIRQDisable(int port)
00236 {
00237 uint32_t base = UARTDesc[port].base;
00238
00239 HWREG(base + UART_O_IM) &=
00240 ~(UART_IM_TXIM | UART_IM_RXIM | UART_IM_RTIM);
00241 }
00242
00243
00244 #define UART_PORT(port) \
00245 \
00246 static unsigned char \
00247 uart ## port ## _txbuffer[CONFIG_UART ## port ## _TXBUFSIZE]; \
00248 static unsigned char \
00249 uart ## port ## _rxbuffer[CONFIG_UART ## port ## _RXBUFSIZE]; \
00250 \
00251 \
00252 static DECLARE_ISR(uart ## port ## _irq_handler) \
00253 { \
00254 uart_common_irq_handler(port); \
00255 } \
00256 \
00257 \
00258 static void \
00259 uart ## port ## _txStart(struct SerialHardware *_hw) \
00260 { \
00261 struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo; \
00262 struct CM3Serial *hw = (struct CM3Serial *)_hw; \
00263 \
00264 if (hw->sending) \
00265 return; \
00266 lm3s_uartPutChar(UART ## port ## _BASE, fifo_pop(txfifo)); \
00267 if (!fifo_isempty(txfifo)) \
00268 { \
00269 HWREG(UART ## port ## _BASE + UART_O_IM) |= \
00270 UART_IM_TXIM; \
00271 hw->sending = true; \
00272 } \
00273 } \
00274 \
00275 static void \
00276 uart ## port ## _setbaudrate(UNUSED_ARG(struct SerialHardware *, hw), \
00277 unsigned long baud) \
00278 { \
00279 lm3s_uartSetBaudRate(UART ## port ## _BASE, baud); \
00280 } \
00281 \
00282 static void \
00283 uart ## port ## _setparity(UNUSED_ARG(struct SerialHardware *, hw), \
00284 int parity) \
00285 { \
00286 lm3s_uartSetParity(UART ## port ## _BASE, parity); \
00287 } \
00288 \
00289 static void \
00290 uart ## port ## _cleanup(struct SerialHardware *_hw) \
00291 { \
00292 struct CM3Serial *hw = (struct CM3Serial *)_hw; \
00293 \
00294 hw->sending = false; \
00295 lm3s_uartIRQDisable(port); \
00296 lm3s_uartClear(UART ## port ## _BASE); \
00297 lm3s_uartDisable(UART ## port ## _BASE); \
00298 } \
00299 \
00300 static void \
00301 uart ## port ## _init(UNUSED_ARG(struct SerialHardware *, hw), \
00302 UNUSED_ARG(struct Serial *, ser)) \
00303 { \
00304 lm3s_uartInit(port); \
00305 lm3s_uartEnable(UART ## port ## _BASE); \
00306 lm3s_uartIRQEnable(port, uart ## port ## _irq_handler); \
00307 } \
00308 \
00309 \
00310 static const struct SerialHardwareVT UART ## port ## _VT = \
00311 { \
00312 .init = uart ## port ## _init, \
00313 .cleanup = uart ## port ## _cleanup, \
00314 .setBaudrate = uart ## port ## _setbaudrate, \
00315 .setParity = uart ## port ## _setparity, \
00316 .txStart = uart ## port ## _txStart, \
00317 .txSending = tx_sending, \
00318 };
00319
00320
00321 UART_PORT(0)
00322 UART_PORT(1)
00323 UART_PORT(2)
00324
00325 static struct CM3Serial UARTDesc[SER_CNT] =
00326 {
00327 {
00328 .hw = {
00329 .table = &UART0_VT,
00330 .txbuffer = uart0_txbuffer,
00331 .rxbuffer = uart0_rxbuffer,
00332 .txbuffer_size = sizeof(uart0_txbuffer),
00333 .rxbuffer_size = sizeof(uart0_rxbuffer),
00334 },
00335 .sending = false,
00336 .base = UART0_BASE,
00337 .irq = INT_UART0,
00338 },
00339 {
00340 .hw = {
00341 .table = &UART1_VT,
00342 .txbuffer = uart1_txbuffer,
00343 .rxbuffer = uart1_rxbuffer,
00344 .txbuffer_size = sizeof(uart1_txbuffer),
00345 .rxbuffer_size = sizeof(uart1_rxbuffer),
00346 },
00347 .sending = false,
00348 .base = UART1_BASE,
00349 .irq = INT_UART1,
00350 },
00351 {
00352 .hw = {
00353 .table = &UART2_VT,
00354 .txbuffer = uart2_txbuffer,
00355 .rxbuffer = uart2_rxbuffer,
00356 .txbuffer_size = sizeof(uart2_txbuffer),
00357 .rxbuffer_size = sizeof(uart2_rxbuffer),
00358 },
00359 .sending = false,
00360 .base = UART2_BASE,
00361 .irq = INT_UART2,
00362 },
00363 };
00364
00365 struct SerialHardware *ser_hw_getdesc(int port)
00366 {
00367 ASSERT(port >= 0 && port < SER_CNT);
00368 return &UARTDesc[port].hw;
00369 }