GNU/Linux >> Linux Esercitazione >  >> Linux

Comunicazione seriale a bassa latenza su Linux

Gli schemi di richiesta/risposta tendono ad essere inefficienti e si presentano rapidamente sulla porta seriale. Se sei interessato al throughtput, guarda il protocollo con finestra, come il protocollo di invio file kermit.

Ora, se vuoi attenerti al tuo protocollo e ridurre la latenza, select, poll, read ti daranno all'incirca la stessa latenza, perché come ha indicato Andy Ross, la vera latenza è nella gestione del FIFO hardware.

Se sei fortunato, puoi modificare il comportamento del driver senza patch, ma devi comunque guardare il codice del driver. Tuttavia, il fatto che l'ARM gestisca una frequenza di interruzione di 10 kHz non sarà certamente positivo per le prestazioni complessive del sistema...

Un'altra opzione è riempire il pacchetto in modo da raggiungere ogni volta la soglia FIFO. Confermerà anche se si tratta o meno di un problema di soglia FIFO.

10 msec @ 115200 sono sufficienti per trasmettere 100 byte (supponendo 8N1), quindi quello che stai vedendo è probabilmente dovuto al low_latency flag non è impostato. Prova

setserial /dev/<tty_name> low_latency

Imposterà il flag low_latency, che viene utilizzato dal kernel quando si spostano i dati nel livello 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);
}

Il schedule_work call potrebbe essere responsabile della latenza di 10 msec che osservi.


Le porte seriali su Linux sono "avvolte" in costrutti terminali in stile unix, che ti colpiscono con 1 tick lag, ovvero 10 ms. Prova se stty -F /dev/ttySx raw low_latency aiuta, ma nessuna garanzia.

Su un PC, puoi diventare hardcore e parlare direttamente con le porte seriali standard, problema setserial /dev/ttySx uart none per separare il driver linux dalla porta seriale hw e controllare la porta tramite inb/outb ai registri portuali. L'ho provato, funziona alla grande.

Lo svantaggio è che non ricevi interruzioni quando arrivano i dati e devi eseguire il polling del registro. spesso.

Dovresti essere in grado di fare lo stesso sul lato del dispositivo del braccio, potrebbe essere molto più difficile su una porta seriale esotica hw.


Dopo aver parlato con altri ingegneri dell'argomento, sono giunto alla conclusione che questo problema non è risolvibile nello spazio utente. Dal momento che dobbiamo attraversare il ponte verso la terra del kernel, abbiamo in programma di implementare un modulo del kernel che comunichi il nostro protocollo e ci dia latenze <1ms.

--- modifica ---

Si scopre che mi sbagliavo completamente. Tutto ciò che era necessario era aumentare la frequenza di tick del kernel. I 100 tick predefiniti hanno aggiunto il ritardo di 10 ms. 1000Hz e un bel valore negativo per il processo seriale mi danno il comportamento temporale che volevo raggiungere.


Ecco cosa setserial fa per impostare una bassa latenza su un descrittore di file di una porta:

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

Linux
  1. Presentazione della guida alla comunicazione tra processi in Linux

  2. Linux:come trovare processi utilizzando la porta seriale?

  3. Risoluzione dei problemi di comunicazione di rete lenta o timeout di connessione in Linux

  4. Porta seriale virtuale per Linux

  5. Come posso monitorare i dati su una porta seriale in Linux?

Comunicazione seriale su Linux moderno

Linux:il massimo numero di Unix?

Linux – Porta seriale Raspberrypi?

Linux – Volume della cuffia Bluetooth troppo basso (solo in Arch)?

Risoluzione dei problemi di spazio su disco insufficiente per un server cloud Linux

Limita la larghezza di banda e la latenza in entrata e in uscita in Linux