Sistemas operacionais em tempo real (RTOS) e seus aplicativos

By Lim Jia Zhi, Senior Embedded Software Engineer

Contributed By DigiKey's North American Editors

O que é RTOS

Um sistema operacional em tempo real (RTOS) é um SO leve usado para fácil multitarefa e integração de tarefa em recurso e projetos restritos de tempo, que normalmente é o caso de sistemas embarcados. Além disso, o termo “tempo real” indica previsibilidade/determinismo em tempo de execução ao invés de velocidade pura, portanto, um RTOS pode geralmente ser provado para satisfazer requisitos estritos de tempo real devido ao seu determinismo.

Os conceitos importantes do RTOS são:

Tarefa

As tarefas (também poderia ser chamada de processo/threads) são funções independentes que executam em loops infinitos, em geral cada um responsável por uma característica. As tarefas se executam de forma independente do seu próprio tempo (isolação temporal) e pilha de memória (isolação espacial). A isolação espacial entre tarefas pode ser garantida com o uso de uma unidade de hardware de proteção de memória (MPU), que restringe a região de memória acessível e aciona exceções de falha na violação de acesso. Normalmente, os periféricos internos são memórias mapeadas, logo uma MPU pode ser usada para restringir o acesso a periféricos também.

As tarefas podem estar em estados diferentes:

  • Bloqueado – a tarefa está aguardando um evento (por exemplo, tempo limite de atraso, disponibilidade de dados/recursos)
  • Pronto – a tarefa está pronta para executar na CPU, mas não está executando porque a CPU está em uso por outra tarefa
  • Execução – a tarefa está atribuída para ser executada na CPU

Agendador

Os agendadores em RTOS controlam qual tarefa a ser executada na CPU, com disponibilidade de diferentes algoritmos de agendamento. Normalmente, eles são:

  • Preemptivo – a execução de tarefa pode ser interrompida, caso outra tarefa com prioridade mais alta estiver pronta
  • Cooperativo – a troca de tarefas só acontecerá se a tarefa em execução atual desistir por conta própria

O agendamento preemptivo permite que tarefas de prioridade mais alta interrompam uma tarefa inferior, a fim de cumprir as restrições de tempo real, mas isso gera um custo de mais sobrecarga na troca de contexto.

Comunicação entre tarefas (ITC)

Normalmente, várias tarefas precisarão compartilhar informações ou eventos umas com as outras. A maneira mais simples de compartilhar é ler/escrever variáveis globais compartilhadas de forma direta na RAM, mas isto é indesejável devido ao risco de corromper dados provocados por uma condição de corrida. Uma maneira melhor é ler/escrever variáveis estáticas com escopo de arquivo acessíveis por funções setter e getter, e as condições de corrida podem ser evitadas ao desabilitar interrupções ou usar um objeto de exclusão mútua (mutex) interno à função setter/getter. A maneira mais clara é usar objetos RTOS thread-safe como fila de mensagens para passar informações entre tarefas.

Além do compartilhamento de informações, os objetos RTOS também são capazes de sincronizar a execução de tarefas, porque elas podem ser bloqueadas para aguardar pela disponibilidade de objetos RTOS. A maioria dos RTOS possuem objetos como:

  • Fila de mensagens
    • Fila do “primeiro a entrar, primeiro a sair” (FIFO) para passar dados
    • Os dados podem ser enviados por cópia ou por referência (ponteiro)
    • Usado para enviar dados entre tarefas ou entre interrupção e tarefa
  • Semáforo
    • Pode ser tratado como um contador de referência para registrar disponibilidade de um recurso particular
    • Pode ser um semáforo binário ou de contagem
    • Usado para proteger o uso de recursos ou sincronizar a execução de tarefas
  • Mutex
    • Semelhante ao semáforo binário, geralmente usado para proteger o uso de um único recurso (exclusão mútua)
    • O mutex FreeRTOS vem com um mecanismo de herança de prioridade, para evitar o problema de inversão de prioridade (condição quando a tarefa de alta prioridade termina esperando pela tarefa de baixa prioridade).
  • Caixa de correio
    • Local de armazenamento simples para compartilhar uma variável única
    • Pode ser considerada com uma fila de elemento único
  • Grupo de evento
    • Grupo de condições (disponibilidade de semáforo, fila, sinalizador de evento, etc.)
    • A tarefa pode ser bloqueada e pode esperar que uma condição de combinação específica seja atendida
    • Disponível no Zephyr como API de sondagem, no FreeRTOS como QueueSets

Tique-taque do sistema

O RTOS precisa de uma base de tempo para medir o tempo, normalmente na forma de uma variável do contador de tiques do sistema incrementada em uma interrupção periódica do temporizador de hardware. Com o tique do sistema, um aplicativo pode manter mais do que serviços baseados em tempo (intervalo de execução de tarefa, tempo limite de espera, divisão de tempo) usando apenas um único temporizador de hardware. No entanto, uma taxa mais alta de tiques apenas aumentará a resolução da base de tempo do RTOS, não tornará a execução de software mais rápida.

Por que usar RTOS

Organização

Os aplicativos sempre podem ser escritos de uma forma “bare-metal”, mas conforme a complexidade do código aumenta, ter algum tipo de estrutura ajudará no gerenciamento de diferentes partes do aplicativo, mantendo-os separados. Além disso, com uma forma estruturada de desenvolvimento e uma linguagem de design familiar, um novo membro da equipe pode entender o código e começar a contribuir com mais rapidez. A RFCOM Technologies desenvolveu aplicativos usando diferentes microcontroladores, como Hercules da Texas Instruments, RL78 e RX da Renesas e STM32 da STMicroelectronics em um RTOS diferente. Padrões de projeto semelhantes nos permitem desenvolver aplicativos em diferentes microcontroladores e até mesmo em um RTOS diferente.

Modularidade

Dividir e conquistar. Ao separar recursos em tarefas diferentes, novos recursos podem ser adicionados facilmente sem quebrar outros recursos; desde que o novo recurso não sobrecarregue recursos compartilhados como a CPU e periféricos. Normalmente, o desenvolvimento sem RTOS estará em um grande loop infinito, onde todos os recursos fazem parte do loop. Uma mudança em qualquer recurso dentro do loop terá um impacto em outros recursos, tornando o software difícil de modificar e manter.

Pilhas de comunicação e drivers

Muitos drivers extras ou pilhas como TCP/IP, USB, pilhas BLE e bibliotecas de gráficos são desenvolvidos/portados para RTOSs existentes. Um desenvolvedor de aplicativo pode se concentrar em uma camada de aplicativo do software e reduzir, de forma significativa, o tempo de lançamento no mercado.

Dicas

Alocação estática

O uso de alocação estática de memória para objetos RTOS significa reservar a pilha de memória na RAM para cada objeto RTOS, durante o tempo de compilação. Um exemplo de função de alocação estática em freeRTOS é xTaskCreateStatic (). Isso garante que um objeto RTOS possa ser criado com êxito, evitando o incômodo de lidar com uma possível falha de alocação e tornando o aplicativo mais determinístico.

Em termos de decidir o tamanho da pilha necessário para uma tarefa, ela pode ser executada com um tamanho de pilha maior (mais do que suficiente) e, em seguida, o uso da pilha pode ser verificado em tempo de execução para determinar a marca d'água alta. Também está disponível uma ferramenta de análise de pilha estática.

Camada de abstração do sistema operacional (OSAL) e abstração significativa

Assim como a camada de abstração de hardware (HAL), o uso da camada de abstração RTOS permite que o software aplicativo migre facilmente para outros RTOSs. Os recursos dos RTOSs são bastante semelhantes, portanto, criar OSAL não deve ser muito complicado. Por exemplo:

Usando a API freeRTOS diretamente:

if( xSemaphoreTake( spiMutex, ( TickType_t ) 10 ) == pdTRUE ) { //dosomething }

Envolvendo a API RTOS em OSAL:

if( osalSemTake( spiMutex, 10 ) == true) { //dosomething }

usando a camada de abstração na comunicação entre tarefas para tornar o código mais legível e minimizar o escopo de um objeto RTOS:

if( isSpiReadyWithinMs( 10 ) ) { //doSomething }

Além disso, a abstração também permite que um programador altere o objeto RTOS usado por baixo (por exemplo, de mutex para semáforo de contagem) se houver mais de um módulo SPI disponível. As camadas OSAL e outras ajudam no teste de software, simplificando a inserção de função simulada durante o teste de unidade.

Seleção de intervalo do tique

Idealmente, uma taxa de tiques mais baixa é melhor devido à menor sobrecarga. Para selecionar uma taxa de tiques adequada, o desenvolvedor pode listar as restrições de temporização dos módulos em um aplicativo (intervalo de repetição, duração do tempo limite, etc.). Se houver alguns módulos outliers que precisam de um pequeno intervalo, uma interrupção de temporizador dedicado pode ser considerada para esses módulos, em vez de aumentar a taxa de tiques do RTOS. Se a função de alta frequência for muito curta (por exemplo, escrever para registrar o ligar/desligar de um LED), isso pode ser feito dentro de uma Rotina de Serviço de Interrupção (ISR), caso contrário, o tratamento de interrupção adiada pode ser usado. O tratamento de interrupção adiada é uma técnica de cálculo de interrupção para adiamento dentro de uma tarefa RTOS, a ISR gera depois apenas um evento através do objeto RTOS, em seguida, a tarefa RTOS será desbloqueada pelo evento e fará o cálculo.

Supressão de tiques para aplicação de baixa potência

O “tickless idle” desativa a interrupção de tiques, quando que o sistema estiver ocioso por mais tempo. Uma maneira significativa de o firmware embarcado reduzir o consumo de energia é colocar o sistema no modo de baixa potência pelo maior tempo possível. O tickless idle é implementado ao desabilitar a interrupção periódica de tiques e ao configurar um temporizador de contagem regressiva para interromper, quando uma tarefa bloqueada estiver para ser executada. Se não houver nenhuma tarefa esperando por um tempo limite, a interrupção de tiques pode ser desabilitada indefinidamente até que outra interrupção ocorra (por exemplo, botão pressionado). Por exemplo, no caso de uma baliza Bluetooth de baixa energia (BLE), o MCU pode ser colocado em hibernação entre o intervalo de publicidade. Conforme mostrado na Figura 1, a baliza é colocada no modo de hibernação na maior parte do tempo, consumindo energia de dezenas de µA.

Gráfico do consumo de corrente de uma baliza BLE (clique para ampliar)Figura 1: consumo atual de uma baliza BLE (fonte da imagem: RFCOM)

Conclusão

Um RTOS fornece recursos como agendador, tarefas e objetos RTOS de comunicação entre tarefas, bem como pilhas e drivers de comunicação. Ele permite que os desenvolvedores se concentrem na camada de aplicativo do software embarcado e projetem software multitarefa com facilidade e velocidade. No entanto, assim como qualquer outra ferramenta, ele deve ser usado corretamente para agregar mais valor. Para criar software embarcado seguro, protegido e eficiente, os desenvolvedores devem saber quando usar e como configurar o RTOS.

DigiKey logo

Disclaimer: The opinions, beliefs, and viewpoints expressed by the various authors and/or forum participants on this website do not necessarily reflect the opinions, beliefs, and viewpoints of DigiKey or official policies of DigiKey.

About this author

Image of Lim Jia Zhi

Lim Jia Zhi, Senior Embedded Software Engineer

Lim Jia Zhi is an embedded software engineer, holds a degree in Electrical and Electronics Engineering. He has developed software for devices in IoT solution covering edge gateway and battery-powered edge devices, and also involved in developing safety-critical embedded software. Actively learning ways to design efficient and reliable embedded system, like using design pattern and tools, and having software development lifecycle. (jia.zhi.lim@rfcom-tech.com (+65) 6635 4217)

About this publisher

DigiKey's North American Editors