porAndré Luis Pereira dos Santos

Transferência de structs de dados entre MPUs via protocolos seriais

Quando lidamos com sistemas mais complexos em que existem mais que uma MPU (microcontrolador) e onde elas precisam comunicar-se entre si, devemos considerar alternativas que levem em conta o grau de segurança, confiabilidade e velocidade no tráfego de tais dados.

Quase sempre acabamos pensando em utilizar algum dos muitos protocolos seriais para tal, já que existem em grande quantidade e muitos são extremamente maduros, inclusive para aplicações de alto desempenho. Podemos citar alguns como o CAN, UART, I2C e SPI só pra ficar nos mais famosos.

Quase sempre acabamos por considerar a transferência de dados entre MPUs de forma binária também, justamente porquê em geral isso diminui o tamanho do payload das mensagens, o que implica em uma performance maior.

No entanto precisamos considerar diversas coisas se desejamos implementar uma comunicação nestes moldes entre MPUs.

A primeira é o fato de que se estamos transferindo structs inteiras (aquela struct do C) teremos de garantir que o formato binário deste dado seja lido corretamente pelo sistema receptor. Normalmente isso implica em termos o emissor e receptor rodando uma mesma arquitetura, ou uma arquitetura muito parecida.

Por exemplo, uma struct criada em uma MPU ARM Cortex M3 não poderá ser lida, sem tradução de seu formato binário, por uma outra MCU baseada na arquitetura usada pelo TI MSP430.

Os componentes da struct terão tamanhos diferentes e mesmo a struct pode ser envelopada de uma maneira totalmente diferente, mudando coisas como a maneira com que os dados são alinhados na memória, dentre outras coisas. (ex: um tipo int do ARM Cortex M3 possui 32 bits e o mesmo tipo no MSP430 possui 16 bits)

Para simplificar as coisas, daqui em diante vamos falar em troca de dados entre MPUs de mesma arquitetura através de um barramento serial.

Vou utilizar como exemplo a troca de dado entre dois STM32f103 através de suas UARTs.

Nesse ponto também é saudável que nos preocupemos com a confiabilidade desta transmissão. Dados trafegam através da UART bit a bit por um condutor metálico. São dois fios (uma para ida – TX – e outro para recepção de dados – RX) e mais um fio de GND como referência. Se estes fios não são muito compridos e caso as taxas de transferência não sejam muito altas, a transmissão tende a ocorrer de forma muito confiável.

image Transferência de structs de dados entre MPUs via protocolos seriais
Esquema de uma transmissão serial via UART

Os problemas aparecem quando utilizamos altas taxas de transferência e/ou temos comprimentos maiores para o meio físico de transmissão.

Ficamos ai muito sujeitos a interferência eletromagnética do ambiente ao redor e a interferência criada entre os próprios cabos de RX e TX.

Sobre isto, cheguei em algumas soluções simples, tais como a utilização de cabos blindados. Estes podem ser, inclusive, bons cabos USB devidamente preparados. Cortamos literalmente suas duas pontas e podemos utilizar dois de seus fios de maneira bastante segura para o tráfego serial e um terceiro fio do cabo para ligar os GNDs.

Outra solução é trançar dois cabos (RX e TX) entre si para mitigar a interferência ambiental e a interferência mútua entre os cabos. Esse design é extensivamente utilizado na indústria.

Dessa maneira, agora podemos trafegar dados a velocidades maiores sem que estes sejam perdidos ou sem que sofram corrupção.

Em tratando-se de transmissão via UART podemos também ativar a checagem de paridade de dados proporcionada pelo próprio protocolo. Aumentamos, assim, ainda mais a confiabilidade, às custas de uma pequena penalidade de velocidade, parcialmente compensada pelas medidas anteriores.

É um bom meio termo.

No próximo post irei falar sobre a implementação no software do firmware das transmissão de structs de dados em formato binário.

porAndré Luis Pereira dos Santos

Introdução a Concorrência em GO – 1

Trabalhando em conjunto

Série de artigos:

Concorrência em Go é um tema dos mais interessantes e com aplicações de alto impacto hoje em dia.

E o que é concorrência? E o que é seu irmão, o paralelismo?

Todo processamento paralelo é concorrente, mas nem todo processamento concorrente é paralelo.

No processamento paralelo duas ou mais instruções são executadas ao mesmo tempo em núcleos diferentes.

No processamento concorrente, duas ou mais instruções são enviadas para execução, mas esta execução pode ser feita em um ou mais núcleos.

Quando o escalonador decide executar as instruções em um mesmo núcleo, elas o serão de maneira concorrente, já que concorrerão por uma fatia de tempo de execução neste núcleo. Lembrando que o núcleo de CPU executa uma instrução por vez. (uma simplificação que não leva em conta pipelines em múltiplos estágios etc)

Eventualmente o escalonador deverá migrar instruções para núcleos diferentes disponíveis, e nestes casos, código concorrente irá rodar em paralelo.

A utilização massiva de computadores com diversos núcleos/cpus foi o caminho para continuarmos à escalar o poder de processamento, já que velocidade bruta medida em GHz de clock de CPU estagnou.

Mas com a utilização de concorrência temos uma série de questões a serem resolvidas em nosso código, que se não forem corretamente endereçadas, levam a comportamentos erráticos, respostas incorretas e até mesmo, crashs.

Uma das grandes questões são as race conditions, em português “condições de corrida”.

Este termo vem do fato de que quando introduzimos concorrência e/ou paralelismo em nosso código, introduzimos muitas vezes uma “corrida” para saber quem terá acesso primeiro a determinado dado ou recurso, ou ainda, uma corrida por dados ou recursos em que se perdeu a sincronia que é capas de produzir resultados corretos ao fim do processamento.

Podem ser duas threads, ou no caso de Go, duas goroutines querendo acessar ao mesmo tempo um mesmo dado (data race) ou recurso.

O que acontece se uma goroutine acessa e muda um dado na memória enquanto outra goroutine estava lendo este dado?
E se o dado é apagado por uma goroutine enquanto outra estava lendo ele?

Estes são cenários que podem ser difíceis de debugar e para os quais deve-se prestar muita atenção.

Felizmente Go foi pensada desde o início para escrever código seguro nestas condições e evitar bugs terríveis e que muitas vezes, podem demorar anos para aparecerem.

Falei rapidamente de threads, instruções e goroutines. Agora vamos falar sobre, afinal de contas, O QUE É UMA GOROUTINE?

Uma goroutine é de certa maneira parecida em conceito com uma thread do sistema operacional.

Ela é uma unidade lógica de execução de seu código que roda de maneira independente do restante do software e que faz um trabalho específico.

Uma goroutine, assim que criada, é alocada pelo escalonador do runtime Go de seu software para rodar em algum dos núcleos de CPU disponíveis, incluindo o núcleo em que roda a goroutine principal de seu programa. (sim, em um programa feito em Go, tudo roda dentro de alguma Goroutine, inclusive seu código principal)

Pense em goroutines como uma “thread mais leve” e rápida para ser criada e destruída. Elas consomem pouca memória também.

Com isso, podemos criar goroutines aos milhares, facilmente, mesmo em computadores modestos, sem grandes penalidades de performance.

E isso com os bônus de um gerenciamento descomplicado e grande segurança de uso, com menores chances de bugs comuns em software multithread.

Criamos uma goroutine com a palavra reservada: go.

go func(a Type)

No próximo artigo vamos falar um pouco sobre alguns cuidados para evitar race conditions e outras coisas.

Por fim, se você gostou da iniciativa, e puder, com o QR Code abaixo, pode me pagar um café.

Com ele você me envia um PIX com o valor que você escolher.

Ou se preferir, envie usando minha chave PIX: [email protected]

pague-um-cafe Introdução a Concorrência em GO - 1
porAndré Luis Pereira dos Santos

Go e Concorrência: A Série

Programação Concorente

Artigos da Série:

Talvez a característica mais legal da linguagem Go seja suas primitivas para escrita de código concorrente e as formas adotadas de tornar segura o uso de variáveis nestes ambientes.

Programação concorrente nunca foi um assunto trivial.

Sempre foi fonte de infindáveis bugs, muitas vezes difíceis de detectar e debugar.

Desenvolvedores de várias gerações lidaram com este assunto fazendo uso de mutexes, semáforos etc, fazendo deste tipo de programação parecer quase uma bruxaria.

Estou iniciando uma série de artigos e vídeos a partir de hoje com o intuito de ajudar desenvolvedores da linguagem Go ou aqueles que desejam iniciar seu aprendizado nela, a produzir software que aproveite de maneira mais eficiente e elegante a concorrência.

Material completamente gratuito.

Falarei sobre:

  • problemas que podem aproveitar concorrência em seu processamento
  • cuidados
  • formas de debug e profiling
  • aspectos técnicos e formais
  • boas práticas e padrões
  • dentre outras coisas

Sinto que falta um material detalhado sobre este assunto para os falantes da língua portuguesa, e essa é uma maneira que encontrei para fechar um pouco o gap.

Espero ajudar, inclusive os desenvolvedores mais novos com material da maior qualidade que eu possa produzir.

Por fim, se você gostou da iniciativa, e puder, com o QR Code abaixo, pode me pagar um café.

Com ele você me envia um PIX com o valor que você escolher.

Ou se preferir, envie usando minha chave: [email protected]

pague-um-cafe Go e Concorrência: A Série
porAndré Luis Pereira dos Santos

Analisando tráfego UDP em Go utilizando Machine Learning – Começando

Como dito em post anterior,estou iniciando um pequeno projeto para verificar a viabilidade de uso de algumas bibliotecas em Go (Golang) para capturar pacotes UDP, analisá-los com um algorítimo de ML (Isolation Forest) e gerar alertas para discrepâncias (outliers).

Esse projeto possui potencial de uso em ferramentas de segurança de redes.

Na prática, ao que parece, nada me impediria de capturar tráfego de outros protocolos e fazer o mesmo, mas decidi iniciar com UDP por simplicidade.

Estou na fase de modelagem utilizando-me da biblioteca GoLearn (https://github.com/sjwhitworth/golearn) de ML e a biblioteca do Google Gopacket (https://github.com/google/gopacket) que me disponibiliza captura e processamento de pacotes de rede e outras facilidades relacionadas.

Vou descrever algumas idéias iniciais, já que estou nelas para daí gerar uma prova de conceito:

  • Captura de pacotes durante tráfego normal da rede
  • Filtragem dos pacotes para obtenção só dos que são UDP
  • Gravação dos pacotes e metadados em arquivo CSV que é a amostra de treino
  • Carregamento do CSV e treino da Isolation Forest
  • Passagem em tempo real de tráfego capturado através da Isolation Forest para obtenção de sua pontuação

Dessa maneira, ao final, cada pacote capturado em tempo real passa pela Isolation Forest “treinada” e obtêm-se sua pontuação indicando conforme a faixa, se aquele pacote representa um outlier (discrepância) ou não, possibilitando a emissão de alertas imediatos.

Lembrando que o algorítimo de Isolation Forest é um algorítimo de aprendizagem não-supervisionada.

Basicamente essa é a ideia. Agora vou partir para modelar uma arquitetura que torne possível a reutilização de componentes neste software e que ao mesmo tempo possibilite alto throghput.

*Photo by Robynne Hu on Unsplash

porAndré Luis Pereira dos Santos

Detecção de anomalias de tráfego em redes com ML e Go

Estou desenvolvendo um pequeno projeto para detecção de anomalias que indiquem tráfego malicioso em redes.

A ideia é capturar o tráfego em tempo real com um software feito em Go utilizando a biblioteca do Google gopacket (https://github.com/google/gopacket).

Após isso, utilizar o algorítimo de machine learning Isolation Forest para detectar anomalias (outliers) no tráfego que é capturado no formato pcap.

O Isolation Forest é relativamente rápido e simples de lidar, além de ser um algorítimo não-supervisionado, o que facilita muito as coisas.

A motivação para o desenvolvimento é dar maior proteção para clientes em suas redes, que muitas vezes misturam servidores e estações de trabalho.

Mais tarde pretendo implementar ações pró-ativas e reativas na rede de forma autônoma com base nesta detecção de anomalias.

Em mais alguns dias subirei um repositório no Github com o código liberado como opensource. 🙂

porAndré Luis Pereira dos Santos

Olá, mundo! O Brasil também é nosso!

Estamos de casa nova no Brasil.

Finalmente uma experiência personalizada de oferta de serviços para falantes de português se junta à já conhecida oferta do portal em inglês, voltado ao público internacional.

E além da oferta de serviços, muita informação será fornecida sobre o mercado de TI, tendências, muitas abordagens técnicas e oportunidades de alavancagem de seus negócios por meio de software bem feito, bem testado e corretamente implantado e monitorado.

Visite-nos também em nosso portal internacional clicando aqui.

Clique aqui também, se deseja entrar em contato.