Asynchronous Serial I/O - ttyserver
#include <sys/ioctl.h>
#include <sys.h>
#include <fcntl.h>
pthread_create(&pid, &attr, &tty_shell, 0)
int _tty_server(char *init, int_8 *arg)
The asynchronous serial I/O server or ttyserver provides the ability to input and output serial characters at baud rates upto and including 115200 using a variety of stop,
data and parity options. It has a variety of flow control choices which may be set including hardware flow control, software flow control and no flow control. It has a variety of setpoints
which can be used to generate early interrupts and achieve maximum throughput for the server.
The ttyserver provides the target with simple terminal communications in both the standard COOKED and RAW modes.
Special ioctl() flags (commands) for setup ttyserver:
TIOCSETD
This option allows you to setup the terminal I/O line discipline. The following are arguments that can be used:
• NETLDISC
This is a special option required to support communication with Remedy over serial lines.
• TTYLDISC
This option sets the TTY line discipline for COOKED mode (regular edit mode). This means that backspace characters etc. will be performed by the TTY server in its receive buffer before the data is handed to the
user. It will only pass the data to the user when a carriage return has been received.
• RAWLDISC
This line discipline is called RAW mode. This means that the server will not interpret received characters in any way before passing them to the user. This option also turns off flow control in RAW mode.
• RAWFLDISC
This option turns on flow control in RAW mode.
• ECHO
This option turns on local echo of characters being transmitted in COOKED mode.
• NOECHO
This option turns off local echo of characters being transmitted in COOKED mode.
• PPPLDISC
ppp discipline
• PPPFSLDISC
ppp discipline with flow control software
• PPPFHLDISC
ppp discipline with flow control hardware
SET_TTY_MODE
Allows you to set mode parameters for each serial port channel.
Parameters are passed as an argument in the structure set_tty.
These structure can be found in the file <ioctl.h>
struct set_tty {
uint_8 csize;
uint_8 parity;
uint_8 flow;
uint speed;
uint_8 stop_bits;
uint_8 tty_int_level;
uint_16 timeout_write;
uint_16 rx_buf_size;
uint_16 tx_buf_size;
}Note:
• The csize parameter specifies the character size to use. For example: 5,6,7 or 8.
• The parity parameter specifies the parity bits to use. This value should be: NO_PARITY, EVEN_PARITY or ODD_PARITY.
• The flow parameter specifies whether or not to use hardware flow control. Specify: NO_FLOWCONTROL, CTS_FLOWCONTROL or DTR_FLOWCONTROL.
• The speed parameter specifies the channel speed. This value will be written into the chip UART baudrate register, and must be calculated depending on the chip clock settings.
• The stop_bits parameter specifies the channel stop bits to use.
• The tty_int_level parameter must be set to the interrupt vector that the channel of the corresponding hardware UART will be using.
• The timeout_write parameter specifies the channel data write timeout. This value will be used if flow control is used. If the timeout_write parameter is set to zero, the timeout mechanism will not be used.
• The rx_buf_size is the size of the receive buffer.
• The tx_buf_size is the size of the transmit buffer.
To initialize the server is passed two parameters:
The first parameter is the structure of the configuration of each of the ports that will use the server:
Example:
struct set_tty tty_setup[2];
tty_setup[0].csize = 8;
tty_setup[0].parity = NO_PARITY;
tty_setup[0].flow = NO_FLOWCONTROL;
tty_setup[0].speed = BAUD_VALUE;
tty_setup[0].stop_bits = 1;
tty_setup[0].tty_int_level = 5;
tty_setup[0].timeout_write = 0;
tty_setup[0].rx_buf_size = 64;
tty_setup[0].tx_buf_size = 32;
tty_setup[1].csize = 8;
tty_setup[1].parity = NO_PARITY;
tty_setup[1].flow = NO_FLOWCONTROL;
tty_setup[1].speed = BAUD_VALUE;
tty_setup[1].stop_bits = 1;
tty_setup[1].tty_int_level = 5;
tty_setup[1].timeout_write = 0;
tty_setup[1].rx_buf_size = 128;
tty_setup[1].tx_buf_size = 32;
The second parameter is an array of port numbers that will be initialized:
Set the number of ports that will be given to initialize ttyserver, describe in an array with -1 terminating the list:
Example:
char tty_map[]= { 0, 2, ...-1};
Whre:
'0' – ttyS0 (UART0 on hardware)
'2' – ttyS2 (UART2 on hardware)
...
THREAD Main()
{
pthread_t pid;
pthread_attr_t attr;
struct sched_param myNewPriority;
pthread_t serverid;
struct set_tty *set_tty;
int ioctl_arg;
pthread_attr_init(&attr);
myNewPriority.sched_priority = 5;
pthread_attr_setschedparam(&attr, &myNewPriority);
pthread_attr_setstacksize(&attr,1024);
if(pthread_create(&pid, &attr, &tty_shell, 0)!=0)
{
xprintf("pthread_create = %d\n", errno);
pthread_exit(0);
}
if(dir_register("/dev/ttyS", pid, TYPE_SERVER)==0)
{
xprintf("dir_register = %d\n", errno);
pthread_exit(0);
}
set_tty = malloc(sizeof(struct set_tty));
set_tty->csize = 8;
set_tty->parity = NO_PARITY;
set_tty->flow = NO_FLOWCONTROL;
set_tty->speed = BAUD_RATE;
set_tty->stop_bits = 1;
set_tty->tty_int_level = 4;
set_tty->timeout_write = 0;
ioctl(fd1,SET_TTY_MODE,set_tty);
ioctl_arg = ECHO;
ioctl( fd1, TIOCSETD, &ioctl_arg);
...
}
THREAD tty_shell(void *arg)
{
struct set_tty tty_setup[1];
int_8 tty_map[]= {1,-1}; /* ttyS1*/
tty_setup[0].csize = 8;
tty_setup[0].parity = NO_PARITY;
tty_setup[0].flow = NO_FLOWCONTROL;
tty_setup[0].speed = BAUD_VALUE;
tty_setup[0].stop_bits = 1;
tty_setup[0].tty_int_level = 5;
tty_setup[0].timeout_write = 0;
tty_setup[0].rx_buf_size = 64;
tty_setup[0].tx_buf_size = 32;
/* Start tty server */
if(_tty_server((char*)&tty_setup, (char*)&tty_map[0])==-1)
{
xprintf("Error init tty server ERRNO=%x\n",errno);
pthread_exit(0);
}
}close(), open(), read(), ioctl(), write()