1 /* 2 * File : serial.c 3 * This file is part of RT-Thread RTOS 4 * COPYRIGHT (C) 2006, RT-Thread Development Team 5 * 6 * The license and distribution terms for this file may be 7 * found in the file LICENSE in this distribution or at 8 * http://openlab.rt-thread.com/license/LICENSE 9 * 10 * Change Logs: 11 * Date Author Notes 12 * 2006-08-23 Bernard first version 13 * 2009-05-14 Bernard add RT-THread device interface 14 * 15 * 2011-12-17 nl1031 MicroBlaze 16 */ 17 18 #include <rthw.h> 19 #include <rtthread.h> 20 #include "serial.h" 21 22 typedef volatile rt_uint32_t REG32; 23 struct rt_mb_uart_lite_hw 24 { 25 REG32 Rx_FIFO; // Receiver Holding Register 26 REG32 Tx_FIFO; // Transmitter Holding Register 27 REG32 STAT_REG; // Channel Status Register 28 REG32 CTRL_REG; // Control Register 29 }; 30 31 struct rt_mb_uart_lite 32 { 33 struct rt_device parent; 34 35 struct rt_mb_uart_lite_hw* hw_base; 36 rt_uint16_t peripheral_id; 37 rt_uint32_t baudrate; 38 39 /* reception field */ 40 rt_uint16_t save_index, read_index; 41 rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE]; 42 }; 43 #ifdef RT_USING_UART1 44 struct rt_mb_uart_lite serial1; 45 #endif 46 47 static void rt_hw_serial_isr(void) 48 { 49 unsigned int status; 50 rt_base_t level; 51 struct rt_device* device; 52 struct rt_mb_uart_lite* serial = RT_NULL; 53 54 #ifdef RT_USING_UART1 55 /* serial 1 */ 56 serial = &serial1; 57 #endif 58 RT_ASSERT(serial != RT_NULL); 59 60 /* get generic device object */ 61 device = (rt_device_t)serial; 62 63 /* disable interrupt */ 64 level = rt_hw_interrupt_disable(); 65 66 /* get uart status register */ 67 status = serial->hw_base->STAT_REG; 68 while (status & XUL_SR_RX_FIFO_VALID_DATA) 69 { 70 /* get received character */ 71 serial->rx_buffer[serial->save_index] = serial->hw_base->Rx_FIFO; 72 73 /* move to next position */ 74 serial->save_index ++; 75 if (serial->save_index >= RT_UART_RX_BUFFER_SIZE) 76 serial->save_index = 0; 77 78 /* if the next position is read index, discard this 'read char' */ 79 if (serial->save_index == serial->read_index) 80 { 81 serial->read_index ++; 82 if (serial->read_index >= RT_UART_RX_BUFFER_SIZE) 83 serial->read_index = 0; 84 } 85 status = serial->hw_base->STAT_REG; 86 } 87 /* enable interrupt */ 88 rt_hw_interrupt_enable(level); 89 90 /* indicate to upper layer application */ 91 if (device->rx_indicate != RT_NULL) 92 device->rx_indicate(device, 1); 93 94 } 95 96 static rt_err_t rt_serial_init (rt_device_t dev) 97 { 98 struct rt_mb_uart_lite* serial = (struct rt_mb_uart_lite*) dev; 99 100 RT_ASSERT(serial != RT_NULL); 101 102 RT_ASSERT(serial->peripheral_id != XPAR_UARTLITE_1_DEVICE_ID); 103 104 105 /* reset rx index */ 106 serial->save_index = 0; 107 serial->read_index = 0; 108 109 /* reset rx buffer */ 110 rt_memset(serial->rx_buffer, 0, RT_UART_RX_BUFFER_SIZE); 111 112 return RT_EOK; 113 } 114 115 static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag) 116 { 117 struct rt_mb_uart_lite *serial = (struct rt_mb_uart_lite*)dev; 118 RT_ASSERT(serial != RT_NULL); 119 120 if (dev->flag & RT_DEVICE_FLAG_INT_RX) 121 { 122 /* enable UART rx interrupt */ 123 serial->hw_base->CTRL_REG = XUL_CR_ENABLE_INTR; /* enable interrupt */ 124 125 /* install UART handler */ 126 rt_hw_interrupt_install(serial->peripheral_id, (rt_isr_handler_t)rt_hw_serial_isr, RT_NULL); 127 rt_hw_interrupt_umask(serial->peripheral_id); 128 } 129 130 return RT_EOK; 131 } 132 133 static rt_err_t rt_serial_close(rt_device_t dev) 134 { 135 struct rt_mb_uart_lite *serial = (struct rt_mb_uart_lite*)dev; 136 RT_ASSERT(serial != RT_NULL); 137 138 if (dev->flag & RT_DEVICE_FLAG_INT_RX) 139 { 140 /* disable interrupt */ 141 serial->hw_base->CTRL_REG = 0; /* RxReady interrupt */ 142 } 143 144 return RT_EOK; 145 } 146 147 static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) 148 { 149 rt_uint8_t* ptr; 150 struct rt_mb_uart_lite *serial = (struct rt_mb_uart_lite*)dev; 151 RT_ASSERT(serial != RT_NULL); 152 153 /* point to buffer */ 154 ptr = (rt_uint8_t*) buffer; 155 156 if (dev->flag & RT_DEVICE_FLAG_INT_RX) 157 { 158 while (size) 159 { 160 /* interrupt receive */ 161 rt_base_t level; 162 163 /* disable interrupt */ 164 level = rt_hw_interrupt_disable(); 165 if (serial->read_index != serial->save_index) 166 { 167 *ptr = serial->rx_buffer[serial->read_index]; 168 169 serial->read_index ++; 170 if (serial->read_index >= RT_UART_RX_BUFFER_SIZE) 171 serial->read_index = 0; 172 } 173 else 174 { 175 /* no data in rx buffer */ 176 177 /* enable interrupt */ 178 rt_hw_interrupt_enable(level); 179 break; 180 } 181 182 /* enable interrupt */ 183 rt_hw_interrupt_enable(level); 184 185 ptr ++; size --; 186 } 187 188 return (rt_uint32_t)ptr - (rt_uint32_t)buffer; 189 } 190 else if (dev->flag & RT_DEVICE_FLAG_DMA_RX) 191 { 192 /* not support right now */ 193 RT_ASSERT(0); 194 } 195 else 196 { 197 /* poll mode */ 198 while (size) 199 { 200 /* Wait for Full Rx Buffer */ 201 while (!(serial->hw_base->STAT_REG & XUL_SR_RX_FIFO_VALID_DATA)); 202 203 /* Read Character */ 204 *ptr = serial->hw_base->Rx_FIFO; 205 ptr ++; 206 size --; 207 } 208 209 return (rt_size_t)ptr - (rt_size_t)buffer; 210 } 211 212 return 0; 213 } 214 215 static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) 216 { 217 rt_uint8_t* ptr; 218 struct rt_mb_uart_lite *serial = (struct rt_mb_uart_lite*)dev; 219 RT_ASSERT(serial != RT_NULL); 220 221 ptr = (rt_uint8_t*) buffer; 222 if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY) 223 { 224 if (dev->flag & RT_DEVICE_FLAG_STREAM) 225 { 226 /* it's a stream mode device */ 227 while (size) 228 { 229 /* stream mode */ 230 if (*ptr == '\n') 231 { 232 while (!(serial->hw_base->STAT_REG & XUL_SR_TX_FIFO_EMPTY)); 233 serial->hw_base->Tx_FIFO = '\r'; 234 } 235 236 /* Wait for Empty Tx Buffer */ 237 while (!(serial->hw_base->STAT_REG & XUL_SR_TX_FIFO_EMPTY)); 238 239 /* Transmit Character */ 240 serial->hw_base->Tx_FIFO = *ptr; 241 if (*ptr & 1) 242 rt_hw_board_led_on(2); 243 else 244 rt_hw_board_led_off(2); 245 ptr ++; size --; 246 } 247 } 248 else 249 { 250 while (size) 251 { 252 /* Wait for Empty Tx Buffer */ 253 while (!(serial->hw_base->STAT_REG & XUL_SR_TX_FIFO_EMPTY)); 254 255 /* Transmit Character */ 256 serial->hw_base->Tx_FIFO = *ptr; 257 if (*ptr & 1) 258 rt_hw_board_led_on(2); 259 else 260 rt_hw_board_led_off(2); 261 ptr ++; size --; 262 } 263 } 264 } 265 266 return (rt_size_t)ptr - (rt_size_t)buffer; 267 } 268 269 static rt_err_t rt_serial_control (rt_device_t dev, int cmd, void *args) 270 { 271 return RT_EOK; 272 } 273 274 rt_err_t rt_hw_serial_init() 275 { 276 rt_device_t device; 277 278 #ifndef RT_USING_CONSOLE 279 int Status; 280 281 /* 282 * Initialize the UartLite driver so that it is ready to use. 283 */ 284 Status = XUartLite_Initialize(&uart_lite, RS232_DEVICE_ID); 285 if (Status != XST_SUCCESS) 286 { 287 return; 288 } 289 290 #endif 291 292 #ifdef RT_USING_UART1 293 device = (rt_device_t) &serial1; 294 295 /* init serial device private data */ 296 serial1.hw_base = (struct rt_mb_uart_lite_hw*)XPAR_USB_UART_BASEADDR; 297 serial1.peripheral_id = XPAR_UARTLITE_1_DEVICE_ID; 298 serial1.baudrate = 115200; 299 300 /* set device virtual interface */ 301 device->init = rt_serial_init; 302 device->open = rt_serial_open; 303 device->close = rt_serial_close; 304 device->read = rt_serial_read; 305 device->write = rt_serial_write; 306 device->control = rt_serial_control; 307 308 /* register uart1 on device subsystem */ 309 rt_device_register(device, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX); 310 #endif 311 312 313 return RT_EOK; 314 } 315 316 317