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 * 2010-10-6 wangmeng added sep4020 surpport 11 */ 12 #include <rtthread.h> 13 #include <rthw.h> 14 #include "serial.h" 15 16 /** 17 * @addtogroup SEP4020 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 return RT_EOK; 81 } 82 83 static rt_err_t rt_serial_close(rt_device_t dev) 84 { 85 RT_ASSERT(dev != RT_NULL); 86 return RT_EOK; 87 } 88 89 static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) 90 { 91 rt_uint8_t* ptr; 92 rt_err_t err_code; 93 struct serial_device* uart; 94 95 ptr = buffer; 96 err_code = RT_EOK; 97 uart = (struct serial_device*)dev->user_data; 98 99 if (dev->flag & RT_DEVICE_FLAG_INT_RX) 100 { 101 rt_base_t level; 102 103 /* interrupt mode Rx */ 104 while (size) 105 { 106 if (uart->int_rx->read_index != uart->int_rx->save_index) 107 { 108 *ptr++ = uart->int_rx->rx_buffer[uart->int_rx->read_index]; 109 size --; 110 111 /* disable interrupt */ 112 level = rt_hw_interrupt_disable(); 113 114 uart->int_rx->read_index ++; 115 if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE) 116 uart->int_rx->read_index = 0; 117 118 /* enable interrupt */ 119 rt_hw_interrupt_enable(level); 120 } 121 else 122 { 123 /* set error code */ 124 err_code = -RT_EEMPTY; 125 break; 126 } 127 } 128 } 129 else 130 { 131 /* polling mode */ 132 while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size) 133 { 134 while (uart->uart_device->lsr & USTAT_RCV_READY) 135 { 136 *ptr = uart->uart_device->dlbl_fifo.txfifo & 0xff; 137 ptr ++; 138 } 139 } 140 } 141 142 /* set error code */ 143 rt_set_errno(err_code); 144 return (rt_uint32_t)ptr - (rt_uint32_t)buffer; 145 } 146 147 static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) 148 { 149 rt_uint8_t* ptr; 150 rt_err_t err_code; 151 struct serial_device* uart; 152 153 err_code = RT_EOK; 154 ptr = (rt_uint8_t*)buffer; 155 uart = (struct serial_device*)dev->user_data; 156 157 if (dev->flag & RT_DEVICE_FLAG_INT_TX) 158 { 159 /* interrupt mode Tx */ 160 while (uart->int_tx->save_index != uart->int_tx->write_index) 161 { 162 /* save on tx buffer */ 163 uart->int_tx->tx_buffer[uart->int_tx->save_index] = *ptr++; 164 165 -- size; 166 167 /* move to next position */ 168 uart->int_tx->save_index ++; 169 170 /* wrap save index */ 171 if (uart->int_tx->save_index >= UART_TX_BUFFER_SIZE) 172 uart->int_tx->save_index = 0; 173 } 174 175 /* set error code */ 176 if (size > 0) 177 err_code = -RT_EFULL; 178 } 179 else 180 { 181 /* polling mode */ 182 while (size) 183 { 184 /* 185 * to be polite with serial console add a line feed 186 * to the carriage return character 187 */ 188 if (*ptr == '\n' && (dev->flag & RT_DEVICE_FLAG_STREAM)) 189 { 190 while (!(uart->uart_device->lsr & USTAT_TXB_EMPTY)); 191 uart->uart_device->dlbl_fifo.txfifo = '\r'; 192 } 193 194 while (!(uart->uart_device->lsr & USTAT_TXB_EMPTY)); 195 uart->uart_device->dlbl_fifo.txfifo = (*ptr & 0x1FF); 196 197 ++ptr; --size; 198 } 199 } 200 201 /* set error code */ 202 rt_set_errno(err_code); 203 204 return (rt_uint32_t)ptr - (rt_uint32_t)buffer; 205 } 206 207 static rt_err_t rt_serial_control (rt_device_t dev, int cmd, void *args) 208 { 209 RT_ASSERT(dev != RT_NULL); 210 211 switch (cmd) 212 { 213 case RT_DEVICE_CTRL_SUSPEND: 214 /* suspend device */ 215 dev->flag |= RT_DEVICE_FLAG_SUSPENDED; 216 break; 217 218 case RT_DEVICE_CTRL_RESUME: 219 /* resume device */ 220 dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED; 221 break; 222 } 223 224 return RT_EOK; 225 } 226 227 /* 228 * serial register 229 */ 230 rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct serial_device *serial) 231 { 232 RT_ASSERT(device != RT_NULL); 233 234 device->type = RT_Device_Class_Char; 235 device->rx_indicate = RT_NULL; 236 device->tx_complete = RT_NULL; 237 device->init = rt_serial_init; 238 device->open = rt_serial_open; 239 device->close = rt_serial_close; 240 device->read = rt_serial_read; 241 device->write = rt_serial_write; 242 device->control = rt_serial_control; 243 device->user_data = serial; 244 245 /* register a character device */ 246 return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag); 247 } 248 249 /* ISR for serial interrupt */ 250 void rt_hw_serial_isr(rt_device_t device) 251 { 252 struct serial_device* uart = (struct serial_device*) device->user_data; 253 254 /* interrupt mode receive */ 255 RT_ASSERT(device->flag & RT_DEVICE_FLAG_INT_RX); 256 257 /* save on rx buffer */ 258 while (uart->uart_device->lsr & USTAT_RCV_READY) 259 { 260 rt_serial_savechar(uart, uart->uart_device->dlbl_fifo.rxfifo & 0xff); 261 } 262 263 /* invoke callback */ 264 if (device->rx_indicate != RT_NULL) 265 { 266 rt_size_t rx_length; 267 268 /* get rx length */ 269 rx_length = uart->int_rx->read_index > uart->int_rx->save_index ? 270 UART_RX_BUFFER_SIZE - uart->int_rx->read_index + uart->int_rx->save_index : 271 uart->int_rx->save_index - uart->int_rx->read_index; 272 273 device->rx_indicate(device, rx_length); 274 } 275 } 276 277 /*@}*/ 278 279