Há um truque interessante que você pode fazer se a comunicação estiver em uma direção apenas de cada vez (isto é, comunicação half-duplex). Não funcionará se os dois lados conversarem ao mesmo tempo (full duplex), mas se for o seu tipo típico de comunicação "faça isso" "ok, aqui está a resposta" "agora faça isso" "ok, aqui está a nova resposta" funciona muito bem.
Como o link UART usa uma condição ociosa do transmissor em um nível lógico alto (1), você usaria uma porta AND de 2 entradas e conectaria o TX de cada lado a uma entrada AND. A saída da porta AND é sua entrada para o UART do seu sniffer (é o pino RX). Agora pegue a linha TX do dispositivo B e leve-a para uma porta de E / S no sniffer. Você configurará o sniffer para gerar uma interrupção quando esse pino for de alto a baixo.
Para recapitular: entrada do dispositivo A UART TX -> AND gate. Dispositivo B UART TX -> outra entrada AND gate E pino do farejador GPIO. Saída da porta AND -> sniffer da linha UART RX.
As comunicações UART consistem em um bit inicial, algum número de bits de dados, um bit de paridade opcional e um ou mais bits de parada. Como o estado ocioso é uma lógica alta (1), o início de CADA byte será uma lógica baixa (0) e a interrupção no sniffer será acionada. Enquanto o seu sniffer estiver executando a interrupção de E / S, o hardware do UART coletará bits do portão AND. Quando o UART receber o bit de parada, a interrupção de E / S será realizada por muito tempo e a interrupção do UART RX será acionada.
A rotina de interrupção na troca de IO definirá uma variável "direction" para indicar que as comunicações estão na direção "B-> A". A interrupção de recebimento UART do sniffer examinaria essa variável "direction" e gravaria o byte recém-recebido no buffer apropriado. A interrupção do UART RX retornaria a variável "direction" ao estado "A-> B" padrão:
volatile int direction = 0; /* 0 = A -> B */
void io_interrupt(void)
{
direction = 1; /* switch direction, now B -> A */
}
void uart_interrupt(void)
{
unsigned char b;
b = UART_RX_REG;
if(direction) {
store_byte_to_device_b_sniff_buffer(b);
} else {
store_byte_to_device_a_sniff_buffer(b);
}
direction = 0; /* reset direction to default A -> B */
}
Esse código foi escrito para maior clareza e não necessariamente o que você escreveria em uma situação do mundo real. Pessoalmente, eu faria da "direção" um ponteiro para a estrutura FIFO apropriada, mas isso é outro exercício inteiramente. :-)
Quando o dispositivo A está falando, a linha de E / S não se move (permanece no lógico '1', pois o transmissor UART do dispositivo B está ocioso) e a interrupção do UART RX receberá um byte, veja se a direção é A-> B e armazene os dados nesse buffer. Quando o dispositivo B está falando, a linha de E / S fica baixa assim que o dispositivo B inicia a transferência de dados e a rotina de interrupção de E / S define a direção para indicar que o dispositivo B está falando. A interrupção do UART RX será acionada depois que todos os bits tiverem sido coletados e, como a interrupção de E / S cuidou de definir o registro de direção adequadamente, o byte recebido será armazenado no buffer correto.
Presto: comunicações half-duplex entre dois dispositivos capturados com uma única linha de UART e E / S no sniffer, sem comunicação UART.