Primeiras impressões com o react.o

react.o

react.o, para quem não sabe, é o meu framework para firmware reativa de código aberto e suporte gratuito (enquanto eu puder oferecer).

 

Lancei o projeto em dezembro do ano passado por um desejo de longa data de utilizar event loops, a la QT, em firmware, incluindo os elegantes signal slots para emissão e execução de eventos. Deu que o projeto ganhou um bocadinho de features bacanas (mas sou suspeito para falar) ao ponto que eu fiquei sem resposta à pergunta “Vale a pena usar o react.o?”.

 

Ao passo que o react.o oferece resolução para o problema de concorrência sem RTOS (oh yeah baby) e evita o uso do “super loop de main”, ele também modifica a arquitetura da lógica de negócio da firmware para uma estrutura menos legível e mais engessada – o que pode ser ótimo, nem todo o desenvolvedor sabe aquietar, e imprimir uma arquitetura no projeto pode evitar desastres. Mas como o projeto é diferente e novo, eu ainda não consigo responder à pergunta que fiz no parágrafo anterior: A solução de arquitetura do react.o vai escalar? Vai atender aos requisitos hard realtime em todos os casos de borda? O desenvolvedor realmente pode se jogar às cegas no paradigma reativo sem preocupações? O quanto de custo o react.o insere?

 

E as respostas para essas perguntas eu ainda não tenho, pois preciso estudar muito mais e experimentar muito mais com o projeto. Hoje eu apenas recomendo o uso do projeto apenas para aplicações simples, inclusive comerciais.

 

De qualquer maneira, vamos aos bits – no react.o o paradigma reativo é composto por pares de Queues e Handlers de eventos, você vai programar a lógica de negócio da firmware nesses Handlers e associá-los a Queues que serão preenchidas quando eventos forem emitidos e o react.o vai despachar os eventos aos devidos Handlers para processá-lo, em uma sintaxe que ainda está um pouco amarga (quem ajudar a adocicar a sintaxe ganha meus profundos agradecimentos), mas funciona muito bem. Para que a arquitetura funcione, você vai implementar todos os módulos ao estilo de libraries, módulos auto contidos de responsabilidade única, deixando a inteligência para a camada de lógica de negócio inserida dentro do paradigma reativo.

 

Implementei um produto de controle de temperatura de processos, com aquisição e interface do usuário, usando o react.o, e coloco um pouco de código para ilustrar o uso desse framework.

 

O sensor de temperatura usa o protocolo 1-Wire da Maxim, que exige ações em períodos de até 1us, assim sendo a biblioteca de comunicação com o sensor executa o controle do pino em uma ISR, sem nenhuma relação com o react.o para a comunicação, mas quando o sensor termina de fazer a aquisição (leva em torno de 1 segundo) a biblioteca chama a função owts_on_temperature, em contexto de interrupção, para gerar um evento de nova temperatura adquirida e enviar através do react.o:

 

 

queue_push é a função ISR safe do react.o para inserir um evento novo na Queue, reacto_context_queue serve para obter a Queue no qual o evento será enviado, temperature_buffer é o buffer da Queue e finalmente temperature é o conteúdo do evento em si, no caso, a temperatura diretamente.

 

O Hander que irá processar a temperatura é o control_handler, uma função do módulo “control”, cuja a implementação é de uma histerese on-off para o relé de acionamento.

 

 

queue_peek vai obter o evento da Queue cujo buffer é temperature_buffer e copiá-lo para a variável temperature, e então a função irá atualizar a UI, processar o on-off do controle e chamar owts_start_conversion do módulo OWTS (One Wire Temperature Sensor) para iniciar a próxima aquisição de temperatura, que no final irá chamar a função owts_on_temperature gerando o ciclo de aquisição-atualização-e-controle através do paradigma reativo.

 

Vale ressaltar que o react.o implementa ISR safety e type safety sem sincronizadores ou malabarismos de ponteiros para void. Primeiro o reacto é um Event Loop que roda na main, então não existe concorrência entre os Handlers, nunca haverá interrupção de execução em um Handler, e segundo as Queues do react.o são SPSC (Single Producer Single Consumer) fazendo com que você possa inserir eventos a partir de ISRs sem necessidade de sincronizar ou desabilitar demais interrupções, contanto que você tenha apenas uma fonte geradora para cada Queue.

 

Depois, você pode gerar eventos temporais (Timed Queues) no react.o, ao invés de configurar as interrupções de Timer periódicas individuais (na verdade você vai sempre precisar de uma para atualizar o contador de tempo do react.o). A vantagem é que seus Handlers periódicos vão rodar fora do contexto de interrupção.

 

No projeto, Timed Queues foram usadas para controlar a atualização e o timeout da interface com o usuário:

 

 

timed_event_init vai inicializar uma estrutura de evento e timed_queue_link vai linkar essa estrutura na fila de eventos temporais. Agora é só aguardar o tempo de timeout configurado, no caso 1000 unidades de tempo, que o handler on_one_sec será chamado. Note que o timeout_ev foi inicializado mas não linkado. O link vai acontecer em outro momento em que o timeout será habilitado, pois a função acima é a de inicialização do módulo UI.

 

Abaixo a função que é chamada pela interrupção de pino que detecta quando o usuário apertou algum botão ou gira o encoder:

 

 

ui_push vai apenas gerar um evento na ui_event_buffer, que está configurada para chamar o Handler ui_handler:

 

 

consume_input implementa a lógica da UI e vai linkar o evento de timeout caso o usuário tenha apertado o botão para trocar de tela.

 

Sei que ficou redundante para esse artigo, mas vale mostrar que é praticamente idêntico o fluxo de evento que ocorre para a UI e para o controle, esse fluxo é o grande ganho do react.o – é a resolução da concorrência e o paradigma reativo em ação.

 

Agora, como foi inicializado o react.o? O projeto conta com esse criador de contexto, a context_factory, que faz todas as inicializações a partir de uma struct estática de configuração:

 

 

Depois de desenvolver esse produto de controle eu estou bastante confiante nas vantagens do react.o e acredito que o projeto tem poder de melhorar as arquiteturas de firmwares.

 

Eu notei que grande (grande!) parte dos casos que eu testemunhei de equipes adotando RTOS, após análise eu percebi que não haviam razões técnicas para a adoção, na verdade, equipes adotaram esses sistemas a gosto dos desenvolvedores ou para ganhar uma diretriz de arquitetura engessada, do tipo, o RTOS vai ajudar a organizar funcionalidades ortogonais do produto. Na prática eu vejo pouca gente sabendo realmente como se usa um RTOS. O paradigma multi-thread não é óbvio, nem simples, nem fácil e nem seguro e por isso eu não recomendo que se use a não ser que você tenha fortes razões técnicas para usar.

 

O react.o pode oferecer essa solução de arquitetura, mas sem o pênalti do escalonador de um RTOS. É verdade que o código em uma thread pode ser mais simples do que o código do react.o, mas não o runtime. O runtime do react.o é mais simples e seguro do que o runtime de um RTOS o que vai permitir produtos mais robustos conforme o projeto cresce.

 

E, contra o super loop de main, o react.o é melhor porque ele gerencia as prioridades e as chamadas dos Handlers para você. Essa parte de priorizar em um super loop pode ficar confusa e destrambelhada se feita manualmente em cada módulo chamado no super loop.

 

Ok, mostrei como o react.o é utilizado e como ele se destaca em relação às alternativas, agora cabe aos colegas experimentarem também com o projeto e entrarem em contato, ou via a seção de comentários ou via e-mail (me (arroba) flp.lv) ou via Issues no projeto do Github do react.o, para falar as suas impressões.

 

Vos aguardo ansiosamente!

NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Felipe Lavratti
Engenheiro, desenvolve software para embarcados e Linux, evangelista dos processos de qualidade. Mais informações e redes sociais: http://flp.lv

1
Deixe um comentário

avatar
 
1 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
1 Comment authors
Hugo Oliveira Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Hugo Oliveira
Visitante
Hugo Oliveira

Parece ser bem bacana, Felipe. Assim que tiver um tempo irei testar em uma aplicação no meu trampo.