Desenvolvendo um RTOS - Introdução - Embarcados
Confira neste primeiro artigo da série "Desenvolvendo um RTOS" a definição de um RTOS, kernel cooperativo e preemptivo, além de opções no mercado.
Nesta série de artigos o objetivo será abordar os conceitos de programação que envolvem a criação e operação de um sistema de tempo real, RTOS. Iremos começar com um pouco de teoria falando sobre o que são os sistemas operacionais, suas responsabilidades e onde eles se encaixam no ecossistema embarcado. Os artigos estão sendo co-escritos com o Marcelo Barros, professor da UFU em sistemas embarcados.
Um sistema operacional é um conjunto de código que tem como função principal gerenciar os recursos do sistema. Em geral os principais recursos a serem gerenciados são o processador, a memória e os dispositivos de entrada e saída.
Camadas do SO
Dentro do sistema operacional existem diversos trechos de códigos especializados em atender uma determinada função: interfaces gráficas, drivers de dispositivos, sistemas de arquivos, engines de processamento 3D, etc. Esses códigos visam simplificar a criação das aplicações, permitindo que os programadores se preocupem menos com o hardware e mais com as funcionalidades de seu projeto.
No entanto, no ambiente embarcado existem diversas restrições que podem impedir ou dificultar o uso de um sistema operacional convencional. Em algumas situações pode ser necessário acessar diretamente algum periférico por questão de velocidade; noutras a quantidade de memória ou capacidade de processamento impede a utilização das diversas camadas de software; ou ainda a plataforma de hardware utilizada não possui a implementação do sistema operacional desejado. Estes impedimentos são mais comuns em sistemas embarcados de médio ou baixo custo.
Talvez o maior impedimento no uso de sistemas operacionais em alguns ambientes embarcados seja a capacidade de atendimento de tarefas que exijam tempo real. Por tempo real definimos atividades que possuem um prazo no qual elas devem começar e terminar. Atrasar essas atividades podem trazer problemas ou danos físicos ao sistema.
Visando atender essas restrições foram desenvolvidos os sistemas operacionais de tempo real. Estes sistemas são relativamente simples e possuem o foco voltado para atender as questões de tempo das aplicações. A garantia de tempo é realizada no kernel do sistema. A tabela a seguir apresenta alguns exemplos de sistemas operacionais e seus requisitos de memória.
Sistema Operacional Consumo de Flash (mínimo) Consumo de RAM (mínimo)
VxWorks > 75.000 –
FreeRTOS > 6.000 > 800
uC/OS > 5.000 –
uOS > 2.000 > 200
BRTOS > 2.000 ~ 100
O kernel é uma camada de software do SO responsável por gerenciar e coordenar a execução dos processos segundo um critério. O critério utilizado pode ser a prioridade, a criticidade de uma tarefa, uma sequência de execução pré-definida ou o tempo de re-execução da atividade, visando atingir tempo real.
O kernel pode ser dividido em dois grandes grupos: preemptivos ou cooperativos (não-preemptivos). No kernel cooperativo cada atividade é executada do começo ao fim, de modo que a nova atividade só se inicia quando a anterior termina. Já um kernel preemptivo possui a capacidade de pausar a atividade atual para começar uma segunda atividade. Quando a segunda atividade termina, ou esgota seu tempo de execução, o kernel retorna para a primeira atividade, exatamente no ponto que havia parado.
Os kernels cooperativos são a evolução das arquiteturas baseadas em máquina de estado. Uma das restrições da abordagem baseada em máquinas de estado é que o modelo de execução do código é fixo. As mudanças na operação do programa exige um nova análise da maquina de estado, com um novo projeto e implementação, uma vez que os estados são, em geral, fixos. Não é simples, com a placa em execução, modificar seu comportamento base. Para adicionar ou remover atividades é necessário reescrever o código, recompilar e regravar o dispositivo. Um kernel cooperativo remove essa limitação, permitindo que as tarefas possam ser criadas ou removidas com o sistema em funcionamento.
A base de funcionamento do kernel é a execução de atividades. Essas atividades em geral são definidas por um conjunto de código que poderá, ou não, ser executado, dependendo das condições percebidas pelo kernel.
No próximo artigo iremos apresentar uma definição de processo e como podemos executar um trecho de código que, a princípio, não conhecemos em tempo de compilação. Esta habilidade formará a base do nosso kernel cooperativo.