GNU/Linux >> Tutoriales Linux >  >> Linux

Comunicación serie de baja latencia en Linux

Los esquemas de solicitud/respuesta tienden a ser ineficientes y aparecen rápidamente en el puerto serie. Si está interesado en el rendimiento, mire el protocolo de ventana, como el protocolo de envío de archivos kermit.

Ahora bien, si quiere apegarse a su protocolo y reducir la latencia, seleccionar, sondear, leer le dará aproximadamente la misma latencia, porque como indicó Andy Ross, la latencia real está en el manejo FIFO del hardware.

Si tiene suerte, puede modificar el comportamiento del controlador sin parchear, pero aún necesita mirar el código del controlador. Sin embargo, hacer que el ARM maneje una tasa de interrupción de 10 kHz ciertamente no será bueno para el rendimiento general del sistema...

Otra opción es rellenar su paquete para que alcance el umbral FIFO cada vez. También confirmará si es o no un problema de umbral FIFO.

10 ms @ 115200 es suficiente para transmitir 100 bytes (suponiendo 8N1), por lo que lo que está viendo probablemente se deba a que low_latency la bandera no está configurada. Prueba

setserial /dev/<tty_name> low_latency

Establecerá el indicador low_latency, que utiliza el kernel cuando mueve datos hacia arriba en la capa tty:

void tty_flip_buffer_push(struct tty_struct *tty)
{
         unsigned long flags;
         spin_lock_irqsave(&tty->buf.lock, flags);
         if (tty->buf.tail != NULL)
                 tty->buf.tail->commit = tty->buf.tail->used;
         spin_unlock_irqrestore(&tty->buf.lock, flags);
 
         if (tty->low_latency)
                 flush_to_ldisc(&tty->buf.work);
         else
                 schedule_work(&tty->buf.work);
}

El schedule_work call podría ser responsable de la latencia de 10 ms que observa.


Los puertos serie en Linux están "envueltos" en construcciones de terminal de estilo Unix, lo que lo golpea con un retraso de 1 tic, es decir, 10 ms. Prueba si stty -F /dev/ttySx raw low_latency ayuda, aunque no hay garantías.

En una PC, puede volverse duro y hablar directamente con los puertos serie estándar, emita setserial /dev/ttySx uart none para desvincular el controlador de Linux del puerto serie hw y controlar el puerto a través de inb/outb a los registros portuarios. Lo he intentado, funciona muy bien.

La desventaja es que no recibe interrupciones cuando llegan los datos y tiene que sondear el registro. a menudo.

Debería poder hacer lo mismo en el lado del dispositivo del brazo, puede ser mucho más difícil en el hw exótico del puerto serie.


Después de hablar con algunos ingenieros más sobre el tema, llegué a la conclusión de que este problema no se puede resolver en el espacio del usuario. Dado que necesitamos cruzar el puente hacia kernel land, planeamos implementar un módulo de kernel que hable con nuestro protocolo y nos dé latencias <1 ms.

--- editar ---

Resulta que estaba completamente equivocado. Todo lo que era necesario era aumentar la tasa de ticks del núcleo. Los 100 tics predeterminados agregaron el retraso de 10 ms. 1000 Hz y un buen valor negativo para el proceso en serie me da el comportamiento de tiempo que quería alcanzar.


Esto es lo que setserial hace para establecer una latencia baja en un descriptor de archivo de un puerto:

ioctl(fd, TIOCGSERIAL, &serial);
serial.flags |= ASYNC_LOW_LATENCY;
ioctl(fd, TIOCSSERIAL, &serial);

Linux
  1. Comunicación entre procesos en Linux:sockets y señales

  2. Linux:¿el número principal de Tty de su Unix?

  3. Linux – ¿Puerto serie Raspberrypi?

  4. Puerto serie virtual para Linux

  5. ¿Cómo puedo monitorear datos en un puerto serie en Linux?

Comunicación serial en Linux moderno

Solución de problemas de poco espacio en disco para un servidor en la nube de Linux

Solución de problemas de comunicación de red lenta o tiempos de espera de conexión en Linux

¿Escucha e intérprete del puerto serie de Linux?

Lectura y escritura en puerto serie en C en Linux

Limite el ancho de banda entrante y saliente y la latencia en Linux