Como decodificar com eficiência o sinal serial não padrão
Sou membro de uma equipe de pesquisa que trabalha em um projeto que envolve um ASIC transmissor de RF e seu receptor sem fio, que deve enviar dados para um PC.
O receptor emite um sinal serial rápido , contínuo, assíncrono e não padrão (ou seja, não SPI, I2C, UART, etc.), portanto, meu trabalho é escrever um software de microcontrolador para fazer a interface do receptor com o computador. Atualmente, minha abordagem é usar interrupções acionadas por borda para colocar os dados em um buffer circular e fazer todo o processo de decodificação bit a bit no loop principal. O microcontrolador deve enviar esses dados simultaneamente usando USB (porta de comunicação virtual) para o computador.
Aqui está um problema que estou tendo e estou antecipando:
Não consigo processar os dados em buffer com rapidez suficiente, mesmo com o meu poderoso processador ARM Cortex M3 de 72 MHz. A taxa de bits é de 400 Kbps (2,5 us / bit). Para referência que deixa apenas 180 ciclos por bit (incluindo a decodificação E o ISR, que possui ~ 30 ciclos de sobrecarga!). O MCU também precisa lidar com muitas outras tarefas pesquisadas no loop principal.
O driver da porta virtual USB também é baseado em interrupção. Isso me deixa quase certo de que o driver acabará interrompendo o processador por tanto tempo que ele perde a janela de 2,5 microssegundos (180 ciclos) na qual um bit pode ser transmitido. Não tenho certeza de como normalmente são interrompidos conflitos / raças como essa.
Portanto, a pergunta é simples: o que alguém pode fazer para resolver esses problemas ou essa não é a abordagem correta? Também estou disposto a considerar abordagens menos centradas em software. Por exemplo, usando um chip USB dedicado com algum tipo de máquina de estado de hardware para a decodificação, mas esse é um território desconhecido.
Devo dizer que é raro ver que muitas sugestões de que gosto respondam rapidamente, que respondem bem à sua pergunta. Eu estaria interessado em saber mais sobre as explosões de dados. Eles estão estourados, de repente a toda velocidade e, em seguida, períodos de dados baixos ou é plausível que você passe um longo período com dados contínuos?
Desde que o ASIC tenha poder, ele envia um fluxo contínuo de dados. Não estourou nada. É um aplicativo de detecção médica em tempo real com uma leitura de computador. Já viu um eletrocardiograma?
— perfil completo de Keegan Jay
Tantas ótimas respostas aqui. Vi uma clara divisão entre soluções que envolvem mudanças nas interrupções e soluções que envolvem hardware / lógica digital dedicadas. Coisas como FPGAs e Verilog que eu conheço, mas ainda não tenho experiência, então isso significa que elas devem ser salvas a longo prazo. No curto prazo, @rocketmagnets, o método menos pesado para interrupções é bom. Gosto da elegância de dedicar tarefas domésticas à lógica digital e salvar o ARM para uma computação verdadeira. No futuro, a energia do ARM será usada para análise e filtragem dos dados seriais sem fio.
O sinal é síncrono ou assíncrono?
Assíncrono. 4 bits de início, 10 bits de dados, 2 bits de parada. Devido à natureza do ASIC que está transmitindo, os tempos HI e LO variam muito de chip para chip. Eu já escrevi um algoritmo para deduzir a taxa de transmissão.
Outra resposta: Pare de usar interrupções.
As pessoas saltam para usar interrupções com muita facilidade. Pessoalmente, raramente os uso porque eles realmente perdem muito tempo, como você está descobrindo.
Muitas vezes, é possível escrever um loop principal que controla tudo tão rapidamente, que a latência está dentro das especificações e muito pouco tempo é desperdiçado.
Pode haver algumas coisas no loop que acontecem com mais frequência do que outras. Talvez os bits recebidos, por exemplo, nesse caso, incluam mais desses testes, para que mais do processador seja dedicado a essa tarefa.
Pode haver alguns eventos para os quais a latência dessa abordagem é muito alta. Por exemplo, você pode precisar de um evento com tempo muito preciso. Nesse caso, tenha esse evento em interrupção e tudo o mais no loop.
Eu gosto mais da sua resposta do que da outra pessoa do Rocketmagnet. Em vez de mais hadrware, hardware mais rápido, mais algo mais, o Rocketmagnet sugere: faça menos, melhor e mais simples.
Ok, já vi muitos casos em que interrupções tornam a solução muito melhor. Eles fazem grandes coisas, permitem código bem estruturado, baixa latência e muitas outras vantagens, mas eu tenho que concordar com você aqui. Parece que o processo é tão intenso. 1 controlador pode precisar dedicar toda a sua atenção ao manuseio do fluxo serial. O front-end digital soa ideal para mim, mas muitas vezes você tem alguns micros e nenhum FPGA por perto, quando é um projeto da escola, provavelmente dedicaria um micro para manipulá-lo primeiro e tentaria encaixar um FPGA posteriormente para substituí-lo por custo.
Esta é provavelmente a solução que eu vou usar a curto prazo. Eu esperava evitar isso porque envolve reescrever bastante os drivers seriais existentes, mas é uma solução elegante que está dentro das minhas habilidades em um curto período de tempo.
@ JayKeegan - Sim, provavelmente é o caminho mais rápido para uma solução. PSoC e FPGA podem ser a abordagem para o próximo projeto.
Você poderia usar um FPGA em vez de um microcontrolador para decodificar e armazenar em buffer o fluxo de dados sem fio. Em seguida, use o processador ARM para liberar os buffers dos FPGAs (por exemplo, usando uma interface SPI) e enviar o conteúdo pela porta USB Comm. É um trabalho, mas um FPGA deve ser capaz de acompanhar com facilidade, desde que você consiga atendê-lo com frequência suficiente para garantir que seus buffers de hardware não excedam (ou se você pode lidar com dados descartados em um nível mais alto do protocolo )
Essa pode ser uma excelente solução a longo prazo. Eu esperava receber muitas soluções de lógica / hardware digital, além de soluções de software, porque agora tenho uma desculpa para aprender sobre essas coisas! Infelizmente ainda não tenho experiência com FPGAs.
Fácil: use um microcontrolador PSoC5 .
Você tem toda a facilidade de uso de um microcontrolador, além de conter um CPLD, para poder escrever seus próprios periféricos de hardware no Verilog. Basta escrever seu decodificador de dados seriais no verilog e usar o DMA para transmiti-lo para a porta USB.
Enquanto isso, o poderoso núcleo ARM de 32 bits pode estar girando suas instruções Thumb.
A página de visão geral não lista as frequências do relógio, o que levantou minha suspeita. A folha de dados diz 40MHz (também observei 6mA em 6MHz). Isso é metade do que o OP tem agora. "O MCU também precisa lidar com muitas outras tarefas", por isso pode depender de quais são essas, seja uma boa ideia ou não.
Eles vão até 67MHz. Portanto, é quase tão rápido quanto o processador atual do OP, exceto que a maior parte do trabalho será feita em hardware, deixando a CPU com muito mais tempo livre.
Não olhei para todas as folhas de dados. O primeiro que eu escolhi disse 40MHz.
@stevenvh - Eles têm diferentes graus de velocidade. O terceiro número no PN é o grau de velocidade. (4 = 48 MHz, 6 = 67 MHz).
Essa também é uma solução fantástica a longo prazo, bem como a idéia do FPGA. Eu nunca ouvi falar desse tipo de chip, mas ele traz muitas das funcionalidades do restante da minha placa em um único chip. No futuro, isso pode significar que todo o receptor se encaixa em algo do tamanho de um pen drive, que é a visão do meu líder de projeto. Eu vou aprender Verilog no próximo semestre.
Eu acho que você tem uma escolha clássica de engenharia a fazer: rápido, barato, funciona: escolha duas.
A solução do @ vicatcu é certamente boa, mas se você não pode ou não adiciona mais hardware (e isso inclui um processador mais rápido), é necessário fazer uma escolha. Se esse link serial for o mais importante, você deve permanecer no ISR até que todos os bits tenham sido coletados. Na verdade, 180 instruções por bit não são nada ruins, mas não tente fazer tudo. Quando você detectar o início de uma transferência, gire até que a transferência seja concluída. Coloque o resultado em um FIFO e retome o processamento normal.
Você não diz quanto tempo cada transmissão tem, mas se elas são curtas e estouradas, essa seria uma solução viável. Estou disposto a apostar que sua implementação de porta COM virtual também possui algum buffer de hardware, portanto, um serviço de interrupção "lento", pois não deve apresentar muitos problemas. Quanto ao restante do que o MCU precisa fazer ... você precisa tomar algumas decisões de design.
Esse tipo de solução complementa a abordagem de software do rocketman com a redução do número de drivers baseados em interrupção. Posso manter o driver serial principal que mencionei como baseado em interrupção. Também vou tentar girar até que todo o quadro seja lido como você mencionou.
Antes de tudo, eu já gosto de algumas respostas aqui, e algumas foram aprovadas.
Mas apenas para lançar outra solução possível: dadas as restrições do seu projeto, seria ruim adicionar um segundo microcontrolador (isso envolveria outra execução da placa)? Talvez um simples microcontrolador de 8 bits que se conecte ao seu Cortex-M3 por um periférico rápido como o SPI. O controlador de 8 bits de sua escolha pesquisaria bits e bytes de formato, como na resposta selecionada, mas quando tiver um byte, poderá despejá-lo no registro de dados SPI para transferência.
O lado do córtex-M3 simplesmente interromperia os dados SPI recebidos. Isso reduz a interrupção acionada por borda externa anterior de 400 KHz para 50 KHz.
As duas razões pelas quais estou sugerindo isso são porque alguns dos outros métodos (PSoC ou FPGA adicionado) são um pouco caros (embora isso provavelmente não importe para um projeto acadêmico de baixo volume) e porque podem permitir que você preserve alguns dos a estrutura do seu código atual.
Fora isso, acho que a ideia do PSoC é incrível com o seu próprio periférico personalizado transferindo DMA para USB.
Este é realmente o plano que eu tinha em mente ao postar isso. Se eu não conseguir otimizar o software reduzindo a dependência de interrupções (resposta selecionada), certamente isso é o que farei. Mas sim, isso exigirá outra execução do conselho, provavelmente duas, porque eu sou péssima em acertar meus projetos na primeira vez.
@ JayKeegan, haha ​​bem-vindo ao clube!
Se o seu formato de dados for semelhante ao de um UART, mas a uma taxa de transmissão imprevisível, mas consistente, minha tendência seria usar um CPLD para converter todas as palavras dos dados recebidos no formato SPI ou no padrão assíncrono. Acho que não há necessidade de avançar até o âmbito das CPLDs. Na verdade, mesmo a lógica discreta pode quase ser viável. Se você pudesse gerar um relógio com um smidgin mais que 5x a sua taxa de dados desejada, poderia usar um contador de divisão por cinco e divisão por 16 com alguns portões. Organize o contador de divisão por cinco, para que seja mantido em redefinição sempre que a entrada estiver ociosa e o contador de divisão por 16 estiver em zero. Caso contrário, gere um pulso de clock SPI e bata no contador de divisão por 16 sempre que o contador de divisão por cinco atingir 2.
Dado o relógio 5x, era possível gerar o relógio SPI usando um 16V8 (o menor e mais barato dispositivo lógico programável atualmente disponível). Um segundo 16V8 ou 22V10 poderia ser usado como um divisor de taxa fracionária para gerar o relógio 5x, ou alguém poderia usar um chip um pouco maior (CPLD) e fazer tudo em um.
Editar / Adendo
Após algumas considerações adicionais, se alguém usar um CPLD, poderá adicionar facilmente alguns aprimoramentos adicionais ao circuito. Por exemplo, pode-se facilmente adicionar lógica para que o circuito seja travado até receber pelo menos 1,5 bits de bit de parada, seguidos por 3,5 bits de bit de início; se receber um bit de início muito curto, deve voltar a procurar o bit de parada. Além disso, se alguém estiver usando SPI, poderá usar o sinal / CS para garantir que o dispositivo receptor veja os dados corretamente enquadrados. Se o dispositivo que recebe os dados SPI pode lidar com quadros de 10 bits, pode-se enviar esses quadros diretamente. Caso contrário, cada quadro de dez bits poderá ser enviado como um quadro de 8 bits com o conjunto LSB (7 bits de dados) e um quadro com todos os dados limpos do LSB (3 bits de dados); o relógio SPI seria acelerado durante os bits de parada, para que todos os dados fossem enviados.
Alguns microcontroladores possuem módulos de geração PWM bastante versáteis, que incluem coisas como a capacidade de ser redefinido por um sinal externo e sincronizam seu tempo com a liberação desse sinal. Se o seu microcontrolador puder fazer isso, dependendo de seus recursos exatos, isso poderá simplificar consideravelmente o CPLD ou o circuito de geração de tempo.
Outra abordagem na qual o Rocketmagnet abordou um pouco, seria ter um micro pequeno cujo único objetivo é decodificar os dados seriais e convertê-los em um formato utilizável pelo micro principal. Sua taxa de dados de 400KHz é bastante rápida para decodificação de software, mas algo como um PIC poderia lidar com isso se não precisasse fazer mais nada ao mesmo tempo. Dependendo de quais dispositivos você está familiarizado, isso pode ser mais fácil ou mais difícil do que usar um CPLD.
Tudo isso será muito valioso ao projetar a lógica digital para decodificação. Eu realmente estarei produzindo como SPI. Por enquanto, estou apenas decodificando usando um MCU independente (restrições de tempo). Obrigado!