ser_posix.c
Go to the documentation of this file.
00001 00040 #include "cfg/cfg_ser.h" 00041 00042 #include <cfg/debug.h> 00043 #include <cfg/compiler.h> 00044 00045 #include <drv/ser.h> 00046 #include <drv/ser_p.h> 00047 #include <drv/timer.h> 00048 #include <cpu/power.h> 00049 00050 #include <struct/fifobuf.h> 00051 00052 #include <sys/types.h> 00053 #include <sys/stat.h> 00054 00055 #include <fcntl.h> /* open() */ 00056 #include <unistd.h> /* read(), write() */ 00057 #include <stdlib.h> 00058 #include <termios.h> 00059 00060 static unsigned long BaudRate[] = {300,600,1200,1800,2400,4800,9600,19200,38400,57600,115200}; 00061 static unsigned long BaudSetting[] = {B300,B600,B1200,B1800,B2400,B4800,B9600,B19200,B38400,B57600,B115200}; 00062 00063 00064 /* From the high-level serial driver */ 00065 extern struct Serial ser_handles[SER_CNT]; 00066 00067 /* TX and RX buffers */ 00068 static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE]; 00069 static unsigned char uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE]; 00070 static unsigned char uart1_txbuffer[CONFIG_UART1_TXBUFSIZE]; 00071 static unsigned char uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE]; 00072 static unsigned char uart2_txbuffer[CONFIG_UART2_TXBUFSIZE]; 00073 static unsigned char uart2_rxbuffer[CONFIG_UART2_RXBUFSIZE]; 00074 00075 00076 //Change these to map to the Serial port I use USB connected serial ports 00077 static char* devFile[SER_CNT] = { 00078 "/dev/ttyS0", 00079 "/dev/ttyUSB0", 00080 "/dev/ttyUSB1" 00081 }; 00082 00083 //Make this big enough not criticul as it is running in emulated enviroment 00084 #define SERIAL_RX_STACK_SIZE (KERN_MINSTACKSIZE*3) 00085 PROC_DEFINE_STACK(serial_rx_stack0, SERIAL_RX_STACK_SIZE); 00086 PROC_DEFINE_STACK(serial_rx_stack1, SERIAL_RX_STACK_SIZE); 00087 PROC_DEFINE_STACK(serial_rx_stack2, SERIAL_RX_STACK_SIZE); 00088 00089 cpu_stack_t *serail_rx_stack[] = {serial_rx_stack0,serial_rx_stack1,serial_rx_stack2}; 00090 00091 00095 struct EmulSerial 00096 { 00097 struct SerialHardware hw; 00098 struct Serial *ser; 00099 int fd; 00100 Process *ser_rcv_proc; 00101 }; 00102 00103 static void poll_serial_rcv(void); 00104 00105 static struct termios oldtio,newtio; 00106 00107 00108 /* 00109 * Callbacks 00110 */ 00111 static void uart_init(struct SerialHardware *_hw, struct Serial *ser) 00112 { 00113 struct EmulSerial *hw = (struct EmulSerial *)_hw; 00114 TRACEMSG("uart_init %d\n",ser->unit); 00115 hw->ser = ser; 00116 hw->fd = open(devFile[ser->unit], O_RDWR | O_NOCTTY | O_NDELAY); 00117 ASSERT(hw->fd); 00118 /* Make the file descriptor asynchronous (the manual page says only 00119 O_APPEND and O_NONBLOCK, will work with F_SETFL...) */ 00120 fcntl(hw->fd, F_SETFL, FNDELAY); 00121 tcflush(hw->fd, TCIFLUSH); 00122 tcgetattr(hw->fd,&oldtio); /* save current port settings */ 00123 hw->ser_rcv_proc = proc_new(poll_serial_rcv,hw,SERIAL_RX_STACK_SIZE,serail_rx_stack[ser->unit]); 00124 } 00125 00126 static void uart_cleanup(UNUSED_ARG(struct SerialHardware *, _hw)) 00127 { 00128 struct EmulSerial *hw = (struct EmulSerial *)_hw; 00129 tcsetattr(hw->fd,TCSANOW,&oldtio); 00130 close(hw->fd); 00131 hw->fd = -1; 00132 } 00133 00134 static void uart_txStart(struct SerialHardware * _hw) 00135 { 00136 struct EmulSerial *hw = (struct EmulSerial *)_hw; 00137 00138 while(!fifo_isempty(&hw->ser->txfifo)) 00139 { 00140 char c = fifo_pop(&hw->ser->txfifo); 00141 write(hw->fd, &c, 1); 00142 } 00143 } 00144 00145 static bool uart_txSending(UNUSED_ARG(struct SerialHardware *, _hw)) 00146 { 00147 return false; 00148 } 00149 00150 00151 static void uart_setBaudrate(struct SerialHardware * _hw, unsigned long rate) 00152 { 00153 int i; 00154 struct EmulSerial *hw = (struct EmulSerial *)_hw; 00155 TRACEMSG("rate=%d", rate); 00156 for (i=0;i<sizeof(BaudRate)/sizeof(unsigned long);i++) 00157 if (BaudRate[i]==rate) 00158 break; 00159 if (i<sizeof(BaudRate)/sizeof(unsigned long)) 00160 { 00161 bzero(&newtio, sizeof(newtio)); 00162 newtio.c_cflag = BaudSetting[i] | CS8 | CLOCAL | CREAD; 00163 newtio.c_iflag = IGNPAR ; 00164 newtio.c_oflag &= ~OPOST; 00165 00166 00167 /* set input mode (non-canonical, no echo,...) */ 00168 newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 00169 00170 tcsetattr(hw->fd,TCSANOW,&newtio); 00171 } 00172 else 00173 { 00174 TRACEMSG("invalid rate %d", rate); 00175 ASSERT(i<sizeof(BaudRate)/sizeof(unsigned long)); 00176 } 00177 00178 00179 } 00180 00181 static void uart_setParity(UNUSED_ARG(struct SerialHardware *, _hw), int parity) 00182 { 00183 TRACEMSG("parity=%d", parity); 00184 // TODO 00185 } 00186 00187 // FIXME: move into compiler.h? Ditch? 00188 #if COMPILER_C99 00189 #define C99INIT(name,val) .name = val 00190 #elif defined(__GNUC__) 00191 #define C99INIT(name,val) name: val 00192 #else 00193 #warning No designated initializers, double check your code 00194 #define C99INIT(name,val) (val) 00195 #endif 00196 00197 /* 00198 * High-level interface data structures. 00199 */ 00200 static const struct SerialHardwareVT uart_vtable = 00201 { 00202 C99INIT(init, uart_init), 00203 C99INIT(cleanup, uart_cleanup), 00204 C99INIT(setBaudrate, uart_setBaudrate), 00205 C99INIT(setParity, uart_setParity), 00206 C99INIT(txStart, uart_txStart), 00207 C99INIT(txSending, uart_txSending), 00208 }; 00209 00210 static struct EmulSerial UARTDescs[SER_CNT] = 00211 { 00212 { 00213 C99INIT(hw, ) { 00214 C99INIT(table, &uart_vtable), 00215 C99INIT(txbuffer, uart0_txbuffer), 00216 C99INIT(rxbuffer, uart0_rxbuffer), 00217 C99INIT(txbuffer_size, sizeof(uart0_txbuffer)), 00218 C99INIT(rxbuffer_size, sizeof(uart0_rxbuffer)), 00219 }, 00220 C99INIT(ser, NULL), 00221 C99INIT(fd, -1), 00222 }, 00223 { 00224 C99INIT(hw, ) { 00225 C99INIT(table, &uart_vtable), 00226 C99INIT(txbuffer, uart1_txbuffer), 00227 C99INIT(rxbuffer, uart1_rxbuffer), 00228 C99INIT(txbuffer_size, sizeof(uart1_txbuffer)), 00229 C99INIT(rxbuffer_size, sizeof(uart1_rxbuffer)), 00230 }, 00231 C99INIT(ser, NULL), 00232 C99INIT(fd, -1), 00233 }, 00234 { 00235 C99INIT(hw, ) { 00236 C99INIT(table, &uart_vtable), 00237 C99INIT(txbuffer, uart2_txbuffer), 00238 C99INIT(rxbuffer, uart2_rxbuffer), 00239 C99INIT(txbuffer_size, sizeof(uart2_txbuffer)), 00240 C99INIT(rxbuffer_size, sizeof(uart2_rxbuffer)), 00241 }, 00242 C99INIT(ser, NULL), 00243 C99INIT(fd, -1), 00244 }, 00245 }; 00246 00247 struct SerialHardware *ser_hw_getdesc(int unit) 00248 { 00249 ASSERT(unit < SER_CNT); 00250 return &UARTDescs[unit].hw; 00251 } 00252 static void poll_serial_rcv(void) 00253 { 00254 int res; 00255 int p; 00256 struct EmulSerial *hw = (struct EmulSerial *)proc_currentUserData(); 00257 //TRACEMSG("poll_serial_rcv dev %d\n",hw->ser->unit); 00258 for(;;) 00259 { 00260 while(!fifo_isfull(&hw->ser->rxfifo)) 00261 { 00262 00263 res = read(hw->fd,&p,1); 00264 //TRACEMSG("rcv %c res %d\n",(unsigned char)p,res); 00265 if (res>0) 00266 { 00267 //TRACEMSG("rcv %02x ",p); 00268 //printf("rcv %02x ", (unsigned char)p); 00269 fifo_push_locked(&hw->ser->rxfifo, (unsigned char)p); 00270 } 00271 else if (res==0) 00272 //Delay for 2 ticks if no characters are read 00273 timer_delay(2); 00274 else 00275 //exit if there is and error i.e. the port closes 00276 goto exit_rcv; 00277 } 00278 cpu_relax(); 00279 } 00280 exit_rcv: 00281 return; 00282 }
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)