Preciso de ajuda para encontrar um patch de kernel para obter um VTIME da API tty termios inferior a 100 ms, a fim de diminuir o intervalo entre caracteres. Ele bloqueia a leitura do syscall até o tempo limite do VTIME.
A função n_tty_read() é o ponto de entrada do patch: https://elixir.bootlin.com/linux/latest/source/drivers/tty/n_tty.c#L2131
Existe alguém para me aconselhar? Tenho que usar o modo não canônico (sem protocolo de enquadramento, sem ASCII, sem interrupção). E o parâmetro VMIN é nulo porque todos os comprimentos das mensagens são variáveis. A solução para pesquisar cada caractere é muito cara com um sistema uart múltiplo e implica múltiplas mudanças de contexto de processo.
Extraia o manual dos termios: VTIME Timeout em decisegundos para leitura não canônica (TIME). https://man7.org/linux/man-pages/man3/termios.3.html
É necessário um patch do kernel Linux... É melhor dividir HZ por um valor maior? Ou definir o HZ global para um valor menor?
A API serial do Microsoft Windows é capaz de configurar até 1 ms, mas não o Linux. Portanto, o Windows é melhor para processamento bruto de porta serial. ReadIntervalTimeout : https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddser/ns-ntddser-_serial_timeouts
Extrato de comentário "em modo não canônico ... aceita apenas 4095 caracteres ", acho que o problema está aqui, talvez seja por isso que a fila read_wait não foi ativada.
https://elixir.bootlin.com/linux/latest/source/drivers/tty/n_tty.c#L1667
Tal patch para o kernel é imprudente porque mudaria a API do espaço do usuário. O Linux se esforça para manter uma API consistente, e o patch solicitado provavelmente quebraria os aplicativos existentes.
Mesmo que tal patch para o kernel não tenha alterado a API, não é provável que seja confiável e atinja seu(s) objetivo(s) não declarado(s). Você não pode ou não deve confiar apenas nas configurações de VMIN e VTIME para detectar mensagens separadas por tempo.
Se a UART utilizar um FIFO para armazenar em buffer os dados de entrada, esse buffer de hardware ocultará o espaçamento entre caracteres que o software pode detectar. Da mesma forma, quando o driver UART estiver usando DMA para armazenar os dados recebidos, o tempo entre caracteres será obscurecido.
O manuseio dos termios está pelo menos uma camada completa acima do driver do dispositivo UART. A camada termios simplesmente não vê as mesmas informações de tempo que estavam na conexão depois que os bytes são manipulados/armazenados em buffer pelo UART e seu driver.
Se você acha que o Windows é mais adequado para o seu aplicativo, você deve usá-lo. Mas esteja avisado de que o que é anunciado não é necessariamente o que você receberá. Essa API do Windows apenas anuncia a especificação de um tempo limite com precisão de milissegundos . Isso não significa que você realmente obterá tal precisão . Por exemplo, existem avisos de que:
Não, você persiste em procurar no lugar errado.
Como tentei apontar para você anteriormente (referindo-me a esta postagem ), a solução confiável requer um temporizador para detectar um receptor UART ocioso. No entanto, mesmo quando o hardware UART implementa um tempo limite do receptor (em dois drivers Linux que revisei), o recurso é usado apenas para abortar a operação DMA atual/ativa.
Como o tempo limite do receptor (possivelmente) detectou o fim de uma mensagem separada por tempo, esse evento/informação precisa ser transmitido para a camada termios quando o driver UART passa os dados recebidos. Esta é a informação que falta que o termios precisa para uma nova variação do modo
VMIN > 0
brutoVTIME > 0
. Em vez de termios verificar o tempo limite entre caracteres, nesta nova variação o driver UART precisa indicar esse evento de tempo limite com os dados recebidos.Esse não é um patch de kernel trivial.
Esperançosamente, encontrei algumas explicações e concluí que estamos diante de uma obsolência de APIs que implicava ser contornada pelo consumo excessivo de CPUs.
A granularidade do tempo limite VTIME foi historicamente definida como a unidade de intervalo entre bytes (VTIME definido pelo POSIX = 100ms). O intervalo entre bytes usado atualmente pelo Linux ainda corresponde a uma linha serial de 110 bauds ( cento e dez ). Mas hoje em dia, por exemplo, com uma linha serial de 115.200 bauds, a duração do TX de um byte é de aproximadamente 100 µs (microssegundo).
Alan Cox: RE: comportamento dos termos VMIN e VTIME
POSIX 2007 junho §11.1.7 Processamento de entrada em modo não canônico
O Manual de Referência da Biblioteca GNU C, para versão 2.37, §17.4.10 Entrada Não Canônica
2005 The SCO Group, Inc. § Processamento de entrada em modo não canônico
Para propor um patch que mantenha a compatibilidade da API do kernel, acho que uma solução de desvio é a principal possível: é usar o valor do parâmetro VEOF (valor de char não assinado não utilizado) do modo CANON para ajustar o VTIME (adicionar um fator de divisão ao valor de tempo limite antes de aplicar a função schedule_timeout ), que será aplicado à função de leitura do modo NÃO-CANON.
Use o valor VEOF que não é usado no modo não canon: https://elixir.bootlin.com/linux/latest/source/include/linux/tty.h#L39
Aplique a divisão aqui: por exemplo, se o valor VEOF for diferente do valor padrão, aplique para reduzir o tempo limite de VTIME. https://elixir.bootlin.com/linux/latest/source/drivers/tty/n_tty.c#L2196