Opening serial port in linux

How to connect to a serial port on Linux

Question: I need to access the management terminal of a hardware switch/router (e.g., Cisco Catalyst or HP ProCurve) via its console port. The switch console port is connected to the serial port of my Linux box. How can I connect to the serial port from a Linux terminal?

First of all, let’s assume that you have already connected the serial port of your Linux box to a switch console port via a serial cable.

To connect a Linux terminal to the serial port of your Linux system, you can use a command-line screen manager tool called screen .

Install screen on Linux

For Ubuntu, Debian or Linux Mint:

To install screen on Ubuntu, Debian or Linux Mint:

$ sudo apt-get install screen

For CentOS, Fedora or RHEL:

To install screen on CentOS, Fedora, or RHEL:

Connect to a Serial Port with screen utility

Traditionally in Linux, the first serial port (COM1) is assigned a name /dev/ttyS0 , the second serial port (COM2) assigned /dev/ttyS1 , etc. If you specify a serial port name as the first argument of the screen command, the current terminal window where you run screen will be directly connected to the serial port.

Thus, to connect to a serial port, simply run the following command from a terminal:

Optionally, you can specify baud rate (e.g., 1200, 9600, 19200) as the second parameter as follows.

Once connected to a serial port, you will then be able to access the switch console port from the terminal.

To terminate the current screen session, type Ctrl-A + k . If you want to temporarily detach from the screen session, type Ctrl-A + d . After detached, you can re-attached to the session later by running:

Support Xmodulo

This website is made possible by minimal ads and your gracious donation via PayPal or credit card

Please note that this article is published by Xmodulo.com under a Creative Commons Attribution-ShareAlike 3.0 Unported License. If you would like to use the whole or any part of this article, you need to cite this web page at Xmodulo.com as the original source.

Источник

How to open serial port in linux without changing any pin?

Just to clarify — in Linux at least, calling open(«/dev/ttyUSB0», os.RDWR) makes both the RTS and the DTR lines go up in the serial port. After the port has been opened, RTS can be set to low again by calling ioctl. However, the question is — how to open the device without setting RTS high even momentarily?

stty requires redirecting the output to the terminal to have any effects (obviously) and doing stty clocal > /dev/ttyUSB0 obviously opens the serial port before doing the action. So, stty will also cause the RTS line to go high, atleast momentarily.

Читайте также:  Linux wifi driver rtl8821ce

4 Answers 4

I have no idea why you’d want to do this, but this can be done pretty easily by modifying the linux kernel driver for your serial console so it doesn’t toggle RTS. For example, for the 8250-series driver in drivers/tty/serial/8250/ you could change every write to the MCR register (UART_MCR) to ensure that bit 1 (mask is UART_MCR_RTS) is never set.

Since it’s abstracted away in userspace, you’re out of luck if you want to do this without modifying the kernel driver.

«I have no idea why you’d want to do this» -> it’s very common for embedded bootloaders to have RTS connected to the reset pin and DTR connected to the bootloader select pin (or vice versa). If the reset pin is toggled, even for a fraction of a microsecond, the chip will reset. This means that it isn’t easy to use the control lines for this purpose if you’re also using the serial port for general communication with the device. not without disconnecting the control lines first 🙁

I see, it’s sort of hijacking the control flow line to reset into a programming state right before serial data is sent. Convenient, at least until design changes from having a tiny microcontroller to use a quad-core SoC running Linux and the hardware engineer doesn’t bother to consult anyone on changes required to the programming model.

@cha5on Yeah, it’s definitely a hack, better to have a real upload protocol that doesn’t interfere with the serial lines, unfortunately in the real world many devices just expose a USB port with a serial interface behind that does just that, so you need to either work with that or spend time modding the device (or throw it away).

Having the same problem, I’d give it a try by patching the ftdi_sio kernel driver. You just need to uncomment a small piece of code in ftdi_dtr_rts() like this:

static void ftdi_dtr_rts(struct usb_serial_port *port, int on) < . /* drop RTS and DTR */ if (on) set_mctrl(port, TIOCM_DTR /*| TIOCM_RTS*/); // 

and the RTS handshake line is not longer changed upon open() call. Note, that the uart than might not longer working with RTS/CTS hardware handshake, as long as your modified kernel driver is loaded. But you can still control the state of the RTS handshake line manually by calling e.g.:

 int opins = TIOCM_RTS; ioctl(tty_fd, TIOCMBIC, &opins); 

I'd tested this with the Ctrl+A+G command of picocom 2.3a, running Kubuntu 16.04 64 bit and Ftdi FT2232H based usb uart adapter.

You might find more details on this topic here.

Checking picocom.c, it uses O_NONBLOCK : tty_fd = open(opts.port, O_RDWR | O_NONBLOCK | O_NOCTTY); and it behaves as described above.

A change in the DTR pin can be (eventually) avoided using the command line

This has the effect of making DTR turn on; and subsequently when the port is opened and closed, DTR is not affected.

And there is code there to do the same thing from python via termios , this can be done before opening the port via pyserial:

import termios path = '/dev/ttyACM0' # Disable reset after hangup with open(path) as f: attrs = termios.tcgetattr(f) attrs[2] = attrs[2] & ~termios.HUPCL termios.tcsetattr(f, termios.TCSAFLUSH, attrs) 

The OP was running this on a Raspberry Pi, but I just tried it on Linux Mint on x86_64, it worked. I don't know how RTS is affected.

The reason I find this useful, is for communication with an Arduino Nano - which has a USB-> serial chip on board - and normally the Arduino gets reset every time you open the serial port from linux (rising edge of DTR causes reset). For some applications, this is not a problem, but it's clearly useful to avoid this for other applications, and it's not so easy to remove that tiny capacitor from the Arduino which connects DTR to reset.

You will still get a single reset when the stty command is executed (after plugging in the USB cable). But at least you can then keep opening and closing the serial port after that without further resets.

Источник

How to open, read, and write from serial port in C?

I am a little bit confused about reading and writing to a serial port. I have a USB device in Linux that uses the FTDI USB serial device converter driver. When I plug it in, it creates: /dev/ttyUSB1. I thought itd be simple to open and read/write from it in C. I know the baud rate and parity information, but it seems like there is no standard for this? Am I missing something, or can someone point me in the right direction?

EDIT: I'd look at ribram's link. However, the point remains that while a serial device is represented as a file, devices often have more specific interfaces implemented via system calls like ioctl and fcntl .

Understanding UNIX termios VMIN and VTIME is a great resource to understand VTIME and VMIN which are used to handle the blocking characteristics of a read() on a serial port.

Do not use code from Frerking's "Serial Programming HOWTO" as mentioned in the first comment. They are not written to be POSIX compliant, so the code examples are not portable and may not work reliably for you.

2 Answers 2

I wrote this a long time ago (from years 1985-1992, with just a few tweaks since then), and just copy and paste the bits needed into each project.

You must call cfmakeraw on a tty obtained from tcgetattr . You cannot zero-out a struct termios , configure it, and then set the tty with tcsetattr . If you use the zero-out method, then you will experience unexplained intermittent failures, especially on the BSDs and OS X. "Unexplained intermittent failures" include hanging in read(3) .

#include #include #include #include #include int set_interface_attribs (int fd, int speed, int parity) < struct termios tty; if (tcgetattr (fd, &tty) != 0) < error_message ("error %d from tcgetattr", errno); return -1; >cfsetospeed (&tty, speed); cfsetispeed (&tty, speed); tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars // disable IGNBRK for mismatched speed tests; otherwise receive break // as \000 chars tty.c_iflag &= ~IGNBRK; // disable break processing tty.c_lflag = 0; // no signaling chars, no echo, // no canonical processing tty.c_oflag = 0; // no remapping, no delays tty.c_cc[VMIN] = 0; // read doesn't block tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls, // enable reading tty.c_cflag &= ~(PARENB | PARODD); // shut off parity tty.c_cflag |= parity; tty.c_cflag &= ~CSTOPB; tty.c_cflag &= ~CRTSCTS; if (tcsetattr (fd, TCSANOW, &tty) != 0) < error_message ("error %d from tcsetattr", errno); return -1; >return 0; > void set_blocking (int fd, int should_block) < struct termios tty; memset (&tty, 0, sizeof tty); if (tcgetattr (fd, &tty) != 0) < error_message ("error %d from tggetattr", errno); return; >tty.c_cc[VMIN] = should_block ? 1 : 0; tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout if (tcsetattr (fd, TCSANOW, &tty) != 0) error_message ("error %d setting term attributes", errno); > . char *portname = "/dev/ttyUSB1" . int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) < error_message ("error %d opening %s: %s", errno, portname, strerror (errno)); return; >set_interface_attribs (fd, B115200, 0); // set speed to 115,200 bps, 8n1 (no parity) set_blocking (fd, 0); // set no blocking write (fd, "hello!\n", 7); // send 7 character greeting usleep ((7 + 25) * 100); // sleep enough to transmit the 7 plus // receive 25: approx 100 uS per char transmit char buf [100]; int n = read (fd, buf, sizeof buf); // read up to 100 characters if ready to read 

The values for speed are B115200 , B230400 , B9600 , B19200 , B38400 , B57600 , B1200 , B2400 , B4800 , etc. The values for parity are 0 (meaning no parity), PARENB|PARODD (enable parity and use odd), PARENB (enable parity and use even), PARENB|PARODD|CMSPAR (mark parity), and PARENB|CMSPAR (space parity).

"Blocking" sets whether a read() on the port waits for the specified number of characters to arrive. Setting no blocking means that a read() returns however many characters are available without waiting for more, up to the buffer limit.

CMSPAR is needed only for choosing mark and space parity, which is uncommon. For most applications, it can be omitted. My header file /usr/include/bits/termios.h enables definition of CMSPAR only if the preprocessor symbol __USE_MISC is defined. That definition occurs (in features.h ) with

#if defined _BSD_SOURCE || defined _SVID_SOURCE #define __USE_MISC 1 #endif 

The introductory comments of says:

/* These are defined by the user (or the compiler) to specify the desired environment: . _BSD_SOURCE ISO C, POSIX, and 4.3BSD things. _SVID_SOURCE ISO C, POSIX, and SVID things. . */ 

Источник

Оцените статью
Adblock
detector