1 /* 2 * File : serial.c 3 * This file is part of RT-Thread RTOS 4 * COPYRIGHT (C) 2010, 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://www.rt-thread.org/license/LICENSE 9 * 10 * Change Logs: 11 * Date Author Notes 12 * 2009-02-05 Bernard first version 13 * 2009-10-25 Bernard fix rt_serial_read bug when there is no data 14 * in the buffer. 15 * 2010-03-29 Bernard cleanup code. 16 * 2010-03-30 Kyle Ported from STM32 to AVR32. 17 */ 18 19 #include "serial.h" 20 #include "compiler.h" 21 #include "usart.h" 22 23 struct rt_device _rt_usart_device; 24 struct avr32_serial_int_rx _rt_usart_rx; 25 struct avr32_serial_device uart = 26 { 27 .uart_device = (avr32_usart_t *) &AVR32_USART1, 28 .int_rx = &_rt_usart_rx 29 }; 30 31 /** 32 * @addtogroup AVR32UC3 33 */ 34 /*@{*/ 35 36 /* RT-Thread Device Interface */ 37 static rt_err_t rt_serial_init (rt_device_t dev) 38 { 39 struct avr32_serial_device* uart = (struct avr32_serial_device*) dev->user_data; 40 41 if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED)) 42 { 43 if (dev->flag & RT_DEVICE_FLAG_INT_RX) 44 { 45 rt_memset(uart->int_rx->rx_buffer, 0, sizeof(uart->int_rx->rx_buffer)); 46 uart->int_rx->read_index = 0; 47 uart->int_rx->save_index = 0; 48 } 49 50 dev->flag |= RT_DEVICE_FLAG_ACTIVATED; 51 } 52 53 return RT_EOK; 54 } 55 56 static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag) 57 { 58 return RT_EOK; 59 } 60 61 static rt_err_t rt_serial_close(rt_device_t dev) 62 { 63 return RT_EOK; 64 } 65 66 static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) 67 { 68 rt_uint8_t* ptr; 69 rt_err_t err_code; 70 struct avr32_serial_device* uart; 71 72 ptr = buffer; 73 err_code = RT_EOK; 74 uart = (struct avr32_serial_device*)dev->user_data; 75 76 if (dev->flag & RT_DEVICE_FLAG_INT_RX) 77 { 78 /* interrupt mode Rx */ 79 while (size) 80 { 81 rt_base_t level; 82 83 /* disable interrupt */ 84 level = rt_hw_interrupt_disable(); 85 86 if (uart->int_rx->read_index != uart->int_rx->save_index) 87 { 88 /* read a character */ 89 *ptr++ = uart->int_rx->rx_buffer[uart->int_rx->read_index]; 90 size--; 91 92 /* move to next position */ 93 uart->int_rx->read_index ++; 94 if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE) 95 uart->int_rx->read_index = 0; 96 } 97 else 98 { 99 /* set error code */ 100 err_code = -RT_EEMPTY; 101 102 /* enable interrupt */ 103 rt_hw_interrupt_enable(level); 104 break; 105 } 106 107 /* enable interrupt */ 108 rt_hw_interrupt_enable(level); 109 } 110 } 111 else 112 { 113 /* polling mode */ 114 while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size) 115 { 116 while (usart_test_hit(uart->uart_device)) 117 { 118 *ptr = uart->uart_device->rhr & 0xff; 119 ptr ++; 120 } 121 } 122 } 123 124 /* set error code */ 125 rt_set_errno(err_code); 126 return (rt_uint32_t)ptr - (rt_uint32_t)buffer; 127 } 128 129 static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) 130 { 131 rt_uint8_t* ptr; 132 rt_err_t err_code; 133 struct avr32_serial_device* uart; 134 135 err_code = RT_EOK; 136 ptr = (rt_uint8_t*)buffer; 137 uart = (struct avr32_serial_device*)dev->user_data; 138 139 if (dev->flag & RT_DEVICE_FLAG_INT_TX) 140 { 141 /* interrupt mode Tx, does not support */ 142 RT_ASSERT(0); 143 } 144 else 145 { 146 /* polling mode */ 147 if (dev->flag & RT_DEVICE_FLAG_STREAM) 148 { 149 /* stream mode */ 150 while (size) 151 { 152 usart_putchar(uart->uart_device, (int) *ptr); 153 154 ++ptr; --size; 155 } 156 } 157 else 158 { 159 /* write data directly */ 160 while (size) 161 { 162 usart_bw_write_char(uart->uart_device, (int) *ptr); 163 164 ++ptr; --size; 165 } 166 } 167 } 168 169 /* set error code */ 170 rt_set_errno(err_code); 171 172 return (rt_uint32_t)ptr - (rt_uint32_t)buffer; 173 } 174 175 static rt_err_t rt_serial_control (rt_device_t dev, int cmd, void *args) 176 { 177 struct avr32_serial_device* uart; 178 179 RT_ASSERT(dev != RT_NULL); 180 181 uart = (struct avr32_serial_device*)dev->user_data; 182 switch (cmd) 183 { 184 case RT_DEVICE_CTRL_SUSPEND: 185 /* suspend device */ 186 dev->flag |= RT_DEVICE_FLAG_SUSPENDED; 187 break; 188 189 case RT_DEVICE_CTRL_RESUME: 190 /* resume device */ 191 dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED; 192 break; 193 } 194 195 return RT_EOK; 196 } 197 198 /* 199 * serial register for STM32 200 * support STM32F103VB and STM32F103ZE 201 */ 202 rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct avr32_serial_device *serial) 203 { 204 RT_ASSERT(device != RT_NULL); 205 206 if ((flag & RT_DEVICE_FLAG_DMA_RX) || 207 (flag & RT_DEVICE_FLAG_INT_TX)) 208 { 209 RT_ASSERT(0); 210 } 211 212 device->type = RT_Device_Class_Char; 213 device->rx_indicate = RT_NULL; 214 device->tx_complete = RT_NULL; 215 device->init = rt_serial_init; 216 device->open = rt_serial_open; 217 device->close = rt_serial_close; 218 device->read = rt_serial_read; 219 device->write = rt_serial_write; 220 device->control = rt_serial_control; 221 device->user_data = serial; 222 223 /* register a character device */ 224 return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag); 225 } 226 227 /* ISR for serial interrupt */ 228 void rt_hw_serial_isr(void) 229 { 230 struct avr32_serial_device* uart = (struct avr32_serial_device*) _rt_usart_device.user_data; 231 rt_base_t level; 232 233 if (usart_test_hit(uart->uart_device)) 234 { 235 /* interrupt mode receive */ 236 RT_ASSERT(device->flag & RT_DEVICE_FLAG_INT_RX); 237 238 /* disable interrupt */ 239 level = rt_hw_interrupt_disable(); 240 241 /* save character */ 242 uart->int_rx->rx_buffer[uart->int_rx->save_index] = uart->uart_device->rhr & 0xff; 243 uart->int_rx->save_index ++; 244 if (uart->int_rx->save_index >= UART_RX_BUFFER_SIZE) 245 uart->int_rx->save_index = 0; 246 247 /* if the next position is read index, discard this 'read char' */ 248 if (uart->int_rx->save_index == uart->int_rx->read_index) 249 { 250 uart->int_rx->read_index ++; 251 if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE) 252 uart->int_rx->read_index = 0; 253 } 254 255 /* enable interrupt */ 256 rt_hw_interrupt_enable(level); 257 258 /* invoke callback */ 259 if (_rt_usart_device.rx_indicate != RT_NULL) 260 { 261 rt_size_t rx_length; 262 263 /* get rx length */ 264 rx_length = uart->int_rx->read_index > uart->int_rx->save_index ? 265 UART_RX_BUFFER_SIZE - uart->int_rx->read_index + uart->int_rx->save_index : 266 uart->int_rx->save_index - uart->int_rx->read_index; 267 268 _rt_usart_device.rx_indicate(&_rt_usart_device, rx_length); 269 } 270 } 271 else 272 { 273 usart_reset_status(uart->uart_device); 274 } 275 } 276 277 /*@}*/ 278