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-03-13 Bernard first version 13 * 2009-04-20 yi.qiu modified according bernard's stm32 version 14 * 2012-02-17 mojingxian modified for bf53x 15 */ 16 17 #include <rtthread.h> 18 19 #include "serial.h" 20 21 /** 22 * @addtogroup BF53X 23 */ 24 /*@{*/ 25 26 /* RT-Thread Device Interface */ 27 /** 28 * This function initializes serial 29 */ 30 static rt_err_t rt_serial_init (rt_device_t dev) 31 { 32 struct serial_device* uart = (struct serial_device*) dev->user_data; 33 34 if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED)) 35 { 36 37 if (dev->flag & RT_DEVICE_FLAG_INT_RX) 38 { 39 rt_memset(uart->int_rx->rx_buffer, 0, 40 sizeof(uart->int_rx->rx_buffer)); 41 uart->int_rx->read_index = uart->int_rx->save_index = 0; 42 } 43 44 if (dev->flag & RT_DEVICE_FLAG_INT_TX) 45 { 46 rt_memset(uart->int_tx->tx_buffer, 0, 47 sizeof(uart->int_tx->tx_buffer)); 48 uart->int_tx->write_index = uart->int_tx->save_index = 0; 49 } 50 51 dev->flag |= RT_DEVICE_FLAG_ACTIVATED; 52 } 53 54 return RT_EOK; 55 } 56 57 /* save a char to serial buffer */ 58 static void rt_serial_savechar(struct serial_device* uart, char ch) 59 { 60 rt_base_t level; 61 62 /* disable interrupt */ 63 level = rt_hw_interrupt_disable(); 64 65 uart->int_rx->rx_buffer[uart->int_rx->save_index] = ch; 66 uart->int_rx->save_index ++; 67 if (uart->int_rx->save_index >= UART_RX_BUFFER_SIZE) 68 uart->int_rx->save_index = 0; 69 70 /* if the next position is read index, discard this 'read char' */ 71 if (uart->int_rx->save_index == uart->int_rx->read_index) 72 { 73 uart->int_rx->read_index ++; 74 if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE) 75 uart->int_rx->read_index = 0; 76 } 77 78 /* enable interrupt */ 79 rt_hw_interrupt_enable(level); 80 } 81 82 static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag) 83 { 84 RT_ASSERT(dev != RT_NULL); 85 86 return RT_EOK; 87 } 88 89 static rt_err_t rt_serial_close(rt_device_t dev) 90 { 91 RT_ASSERT(dev != RT_NULL); 92 93 return RT_EOK; 94 } 95 96 static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) 97 { 98 rt_uint8_t* ptr; 99 rt_err_t err_code; 100 struct serial_device* uart; 101 102 ptr = buffer; 103 err_code = RT_EOK; 104 uart = (struct serial_device*)dev->user_data; 105 106 if (dev->flag & RT_DEVICE_FLAG_INT_RX) 107 { 108 rt_base_t level; 109 110 /* interrupt mode Rx */ 111 while (size) 112 { 113 if (uart->int_rx->read_index != uart->int_rx->save_index) 114 { 115 *ptr++ = uart->int_rx->rx_buffer[uart->int_rx->read_index]; 116 size --; 117 118 /* disable interrupt */ 119 level = rt_hw_interrupt_disable(); 120 121 uart->int_rx->read_index ++; 122 if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE) 123 uart->int_rx->read_index = 0; 124 125 /* enable interrupt */ 126 rt_hw_interrupt_enable(level); 127 } 128 else 129 { 130 /* set error code */ 131 err_code = -RT_EEMPTY; 132 break; 133 } 134 } 135 } 136 else 137 { 138 /* polling mode */ 139 while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size) 140 { 141 //while (uart->uart_device->ustat & USTAT_RCV_READY) 142 { 143 *ptr = uart->uart_device->rbr_thr & 0xff; 144 ptr ++; 145 } 146 } 147 } 148 149 /* set error code */ 150 rt_set_errno(err_code); 151 return (rt_uint32_t)ptr - (rt_uint32_t)buffer; 152 } 153 154 static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) 155 { 156 rt_uint8_t* ptr; 157 rt_err_t err_code; 158 struct serial_device* uart; 159 160 err_code = RT_EOK; 161 ptr = (rt_uint8_t*)buffer; 162 uart = (struct serial_device*)dev->user_data; 163 164 if (dev->flag & RT_DEVICE_FLAG_INT_TX) 165 { 166 /* interrupt mode Tx */ 167 while (uart->int_tx->save_index != uart->int_tx->write_index) 168 { 169 /* save on tx buffer */ 170 uart->int_tx->tx_buffer[uart->int_tx->save_index] = *ptr++; 171 172 -- size; 173 174 /* move to next position */ 175 uart->int_tx->save_index ++; 176 177 /* wrap save index */ 178 if (uart->int_tx->save_index >= UART_TX_BUFFER_SIZE) 179 uart->int_tx->save_index = 0; 180 } 181 182 /* set error code */ 183 if (size > 0) 184 err_code = -RT_EFULL; 185 } 186 else 187 { 188 /* polling mode */ 189 while (size) 190 { 191 /* 192 * to be polite with serial console add a line feed 193 * to the carriage return character 194 */ 195 if (*ptr == '\n' && (dev->flag & RT_DEVICE_FLAG_STREAM)) 196 { 197 while (!(uart->uart_device->lsr & 0x20)); 198 uart->uart_device->rbr_thr = '\r'; 199 } 200 201 while (!(uart->uart_device->lsr & 0x20)); 202 uart->uart_device->rbr_thr = (*ptr & 0xFF); 203 204 ++ptr; --size; 205 } 206 } 207 208 /* set error code */ 209 rt_set_errno(err_code); 210 211 return (rt_uint32_t)ptr - (rt_uint32_t)buffer; 212 } 213 214 static rt_err_t rt_serial_control (rt_device_t dev, int cmd, void *args) 215 { 216 RT_ASSERT(dev != RT_NULL); 217 218 switch (cmd) 219 { 220 case RT_DEVICE_CTRL_SUSPEND: 221 /* suspend device */ 222 dev->flag |= RT_DEVICE_FLAG_SUSPENDED; 223 break; 224 225 case RT_DEVICE_CTRL_RESUME: 226 /* resume device */ 227 dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED; 228 break; 229 } 230 231 return RT_EOK; 232 } 233 234 /* 235 * serial register 236 */ 237 rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct serial_device *serial) 238 { 239 RT_ASSERT(device != RT_NULL); 240 241 device->type = RT_Device_Class_Char; 242 device->rx_indicate = RT_NULL; 243 device->tx_complete = RT_NULL; 244 device->init = rt_serial_init; 245 device->open = rt_serial_open; 246 device->close = rt_serial_close; 247 device->read = rt_serial_read; 248 device->write = rt_serial_write; 249 device->control = rt_serial_control; 250 device->user_data = serial; 251 252 /* register a character device */ 253 return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag); 254 } 255 256 /* ISR for serial interrupt */ 257 void rt_hw_serial_isr(rt_device_t device) 258 { 259 struct serial_device* uart = (struct serial_device*) device->user_data; 260 261 /* interrupt mode receive */ 262 RT_ASSERT(device->flag & RT_DEVICE_FLAG_INT_RX); 263 264 /* save on rx buffer */ 265 //while (uart->uart_device->ustat & USTAT_RCV_READY) 266 { 267 rt_serial_savechar(uart, uart->uart_device->rbr_thr & 0xff); 268 } 269 270 /* invoke callback */ 271 if (device->rx_indicate != RT_NULL) 272 { 273 rt_size_t rx_length; 274 275 /* get rx length */ 276 rx_length = uart->int_rx->read_index > uart->int_rx->save_index ? 277 UART_RX_BUFFER_SIZE - uart->int_rx->read_index + uart->int_rx->save_index : 278 uart->int_rx->save_index - uart->int_rx->read_index; 279 280 device->rx_indicate(device, rx_length); 281 } 282 } 283 284 /*@}*/ 285