Correcta secuencia de inicialización para el puerto serie de Linux
-
24-10-2019 - |
Pregunta
Escribí una aplicación que debe usar puertos serie en Linux, especialmente los TTYUSB. Las operaciones de lectura y escritura se realizan con Standard Select ()/Read () Loop y Write (), y probablemente no hay nada malo en ellas, pero el código de inicialización (o ausencia de alguna parte) daña algo en el subsistema TTY. Aquí está:
vuxboot(string filename, unsigned baud = B115200) : _debug(false) {
_fd = open(filename.c_str(), O_RDWR | O_NOCTTY);
if(_fd < 0) throw new io_error("cannot open port");
// Serial initialization was written with FTDI USB-to-serial converters
// in mind. Anyway, who wants to use non-8n1 protocol?
tcgetattr(_fd, &_termios);
termios tio = {0};
tio.c_iflag = IGNPAR;
tio.c_oflag = 0;
tio.c_cflag = baud | CLOCAL | CREAD | CS8;
tio.c_lflag = 0;
tcflush(_fd, TCIFLUSH);
tcsetattr(_fd, TCSANOW, &tio);
}
Otro tcsetattr(_fd, TCSANOW, &_termios)
Se sienta en el destructor, pero es irrelevante.
Con o sin esta inicialización de termios, las cosas extrañas suceden en el sistema Después de que la aplicación sale. A veces sencillo cat
(o hd
) sale inmediatamente imprimiendo nada o las mismas cosas cada vez, a veces está esperando y no muestra ninguno de los datos que seguramente se envían al puerto; y close()
(read()
también, pero no cada vez) emite un extraño WARNING
a dmesg Refiriéndose a USB-serial.c.
Revisé las decenas de hardware y firmware de veces (incluso en diferentes máquinas) y estoy seguro de que está funcionando según lo previsto; Además, despojé el firmware para imprimir el mismo mensaje una y otra vez.
¿Cómo puedo usar el puerto serie sin destruir nada? Gracias.
Solución 5
Bueno. Puede que esta no sea una solución perfecta ... definitivamente no lo es. Acabo de echar un convertidor FT232 (en realidad frito), y usé uno basado en CP2102. Simplemente funciona ahora (y también es 6 veces más barato).
Otros consejos
Golpeando un WARN_ON
línea puede que significa que has golpeado un error de kernel. Sé que últimamente ha habido mucho trabajo para mejorar el controlador USB-Serial; Sugiero probar un kernel más nuevo y/o preguntar en la lista de correo de linux-usb@vger.kernel.org.
No estoy seguro de qué está mal con su fragmento de código allí, pero esto podría ser útil, si aún no lo ha visto: Guía de programación en serie para sistemas operativos POSIX
Tuve que hacer un poco de interfaz de puertos en serie recientemente y esta biblioteca Funcionó bien, eso podría servir como otro ejemplo.
Solo como una nota al margen realmente, su error verifica open
No es del todo correcto: las condiciones de error se señalan por un valor de retorno de -1. (0 es un FD perfectamente válido, generalmente conectado a Stdin).
Es posible que desee probar:
vuxboot(string filename, unsigned baud = B115200) : _debug(false) {
_fd = open(filename.c_str(), O_RDWR | O_NOCTTY);
if(_fd < 0) throw new io_error("cannot open port");
// Serial initialization was written with FTDI USB-to-serial converters
// in mind. Anyway, who wants to use non-8n1 protocol?
tcgetattr(_fd, &_termios);
- termios tio;
+ termios tio;
+ memcpy(&tio, &_termios, sizeof(struct termios));
tio.c_iflag = IGNPAR;
tio.c_oflag = 0;
tio.c_cflag = baud | CLOCAL | CREAD | CS8;
tio.c_lflag = 0;
tcflush(_fd, TCIFLUSH);
tcsetattr(_fd, TCSANOW, &tio);
}
Esto hace que cualquier campo inesperado de termios
En su sistema, obtenga valores algo razonables.