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