GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery - Parte 1

FreeRTOS 8 bare-metal

Os artigos anteriores desta série indicaram alguns passos muito importantes para o desenvolvimento de firmware usando microcontroladores ARM Cortex-M4 e ferramentas GNU. Até o momento trabalhamos com um projeto bare-metal, ou seja, que não faz uso de um sistema operacional. Este artigo foi dividido em duas partes. Na primeira, entenderemos as razões pelas quais faz-se necessário o uso de um sistema operacional de tempo-real, RTOS, usando o FreeRTOS como alternativa. Na segunda parte serão apresentados os passos que devem ser seguidos para a migração da aplicação bare-metal para a sua versão baseada no FreeRTOS.

 

Sistemas bare-metal

 

Até o momento trabalhamos com desenvolvimento bare-metal, ou seja, o desenvolvedor controla diretamente e manipula o hardware do sistema, executando instruções de acesso aos periféricos do microcontrolador. Pequenos sistemas embarcados que fazem uso desse tipo de arquitetura não possuem controle temporal explícito, fazendo com que o controle de tempo seja obtido por meio de rotinas, tais como delays, escritas pelo próprio desenvolvedor. A isso dá-se o nome de controle implícito de tempo. Uma metodologia muito empregada em sistemas embarcados bare-metal é Background/Foreground, onde a aplicação consiste de um loop infinito sem uma condição de saída. A lógica da aplicação é definida por chamadas a sub-rotinas numa ordem sequencial, dentro do loop, levando em consideração que essa sequência determina o comportamento temporal da aplicação.

 

O loop principal é normalmente chamado de Background, o qual pode ser interrompido (suspendido) por interrupções do microprocessador, que fazem com que rotinas de tratamento a interrupções, ISR, sejam chamadas. A essas rotinas é dado o nome de Foreground. Após o término do processamento dessas funções, o sistema troca o contexto de execução novamente para a operação de Background. Esse tipo de implementação gera um baixo overhead de sistema (memória e processamento), mas possui uma grande desvantagem: não é determinístico no que se refere a tempo. Uma simples alteração no loop principal pode alterar o comportamento temporal de todo processamento seguinte ao ponto modificado. Além disso, uma modificação dentro de uma ISR pode gerar resultados inesperados, pois uma operação de Background pode sofrer incrementos aleatórios no seu tempo de execução ao longo do tempo dependendo da alteração efetuada na rotina de tratamento da interrupção. Deve ser levado em consideração que geralmente operações críticas são realizadas em Foreground, o que faz com que haja uma tendência de adição de código mais do que o recomendado dentro de uma ISR. Como tratamos isso?

 

Por que usar um RTOS?

 

Uma solução seria usar um sistema operacional de tempo real, RTOS, o qual é responsável por garantir que tarefas sejam executadas com determinismo. Dá-se o nome de tarefas aos pedaços de código que executam um trabalho específico e bem definido, em loop, e que podem se comunicar com outras tarefas do sistema por meio de serviços oferecidos pelo kernel do RTOS utilizado. Este artigo não tem o objetivo descrever o que é um RTOS, mas sim apresentar uma visão geral sobre o assunto. Dentre as soluções open-source disponíveis no mercado, uma boa escolha é o FreeRTOS, já que oferece atualizações com frequência e possui uma comunidade grande de desenvolvedores.

 

Muitos sistemas embarcados possuem requisitos de tempo real, ou seja, possuem ações que devem ser tomadas dentro de um período máximo de tempo. Pode-se classificar tais requisitos em soft e hard. Requisitos de tempo real soft impõem que caso o limite de tempo para a execução de uma ação seja eventualmente ultrapassado, uma falha não é gerada, mas uma degradação do sistema é percebida. Já requisitos de tempo real hard impõem que toda ação deve ser executada dentro do seu limite de tempo, caso contrário uma falha no sistema é ocasionada. O FreeRTOS oferece tratamento para ambos requisitos por meio do tratamento das prioridades estabelecidas para as respectivas tarefas.

 

Uma das grandes vantagens do uso de um sistema operacional, seja de tempo real ou de uso genérico, é a modularidade, resultado da criação de tarefas que executam atividades e apresentam interfaces muito bem definidas. Por consequência, a inserção de rotinas de testes torna-se uma tarefa mais simples. Além disso, reuso de código e criação de tarefas orientadas a eventos são outras grandes vantagens.

 

FreeRTOS

 

FreeRTOS é um RTOS desenvolvido pela Real Time Engineers Ltd. que suporta 34 arquiteturas. Possui uma licença GPL modificada, o que permite a proteção do código proprietário do projeto e exige que as mudanças realizadas no código do RTOS em específico sejam disponibilizadas. Deve-se levar em consideração que precisa ser informado, de alguma forma, que o produto desenvolvido com o FreeRTOS faz uso desse sistema operacional.

 

Trata-se de um sistema operacional cujo kernel pode trabalhar de forma preemptiva ou cooperativa, com baixo footprint de memória Flash (4KB a 9KB), escrito predominantemente em C, e oferece suporte a alguns serviços muito interessantes para sincronização entre tarefas: 

 

  • Queues;
  • Binary semaphores;
  • Counting semaphores;
  • Recursive semaphores;
  • Mutexes;
  • Event group (novidade na versão 8.0).

 

Mas o que é necessário para colocamos o FreeRTOS para funcionar na placa STM32F4Discovery? Bem, vamos primeiramente entender a organização do código do FreeRTOS para que tenhamos condições de agregar à aplicação bare-metal somente os arquivos fundamentais para o processo.

 

Primeiramente, faça o download do código do FreeRTOS. Após descompactar o conteúdo do arquivo .zip, o conteúdo abaixo é oferecido:

 

 

A pasta FreeRTOS-Plus contém outros produtos oferecidos pela Real Time Engineers Ltd, sob licenças diferentes, e que não são o foco deste artigo. Já a pasta FreeRTOS contém o que é de mais importante: o código do kernel do FreeRTOS e muitas aplicações de demonstração. O conteúdo dessa última pasta é mostrado abaixo:

 

 

A sub-pasta Source, cujo conteúdo é exibido a seguir, disponibiliza o código do kernel, o qual pode ser caracterizado por três arquivos essenciais: task.c, queue.c e list.c. Além desses, são oferecidas implementações de software timer, por meio do arquivo timers.c, e um módulo com funções responsáveis por tratar co-routines, croutine.c, as quais são usadas para processamento cooperativo. Cada co-routine é uma função implementada como uma tarefa, contendo um loop infinito. No entanto, todas as co-routines de um projeto compartilham uma única stack, ao passo que cada tarefa propriamente dita mantém uma região de stack exclusiva e individual.

 

 

Os arquivos mencionados anteriormente não são dependentes da arquitetura do microprocessador utilizado. No entanto, existe uma outra camada de software que necessita de acesso ao hardware, esta sim dependente da arquitetura escolhida. A essa camada é dado o nome RTOS portable, e é implementada pelos arquivos existentes na pasta portable. Veja o seu conteúdo abaixo:

 

 

Pode-se verificar que seu conteúdo é separado por compilador e arquitetura, como, por exemplo, GCC + ARM Cortex-M4F, IAR + RX600, etc. Existem 18 toolchains e 34 arquiteturas suportados. Além disso, essa camada de abstração de hardware oferece um outro serviço, gerenciamento dinâmico de memória, cuja implementação está na pasta portable/MemMang. Existem quatro arquivos nesse local: heap_1.c, heap_2.c, heap_3.c e heap_4.c. O que são eles?

 

No artigo GNU ARM Cross-toolchain – Configuração stack e heap foi mencionado como reservar espaços da memória volátil do sistema para tais finalidades. Em específico, a região heap é utilizada para alocação dinâmica de memória, o que demanda o uso de um gerenciador de alocação de memória, chamado de allocator. A biblioteca C padrão, como visto no post anterior, oferece uma implementação própria, por meio da API mallocfreerealloc, etc. Mas ela oferece dois grandes perigos para sistemas embarcados com requisitos de tempo-real: não é thread safe e não oferece determinismo. Ou seja, tais funções podem gerar condições de corrida em ambiente multi-thread, por tratarem recursos compartilhados, e não são executadas num tempo constante. Tendo em vista isso, o FreeRTOS oferece, dentro da camada portable, algumas implementações de alocação de memória que endereçam esses problemas, cada uma representada por um desses arquivos.

 

E agora, como começo a minha aplicação? Esse passo fica para a parte 2 do artigo. É a hora em que os leds piscam!

Outros artigos da série

<< GNU ARM Cross-toolchain – OpenOCD + GDBGNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery - Parte 2 >>
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.

Henrique Rossi
Engenheiro eletricista com ênfase em eletrônica e pós-graduado em Engenharia de Software. Comecei um mestrado, mas o interrompi. Especialista na área de sistemas embarcados, com mais de 12 anos de experiência em desenvolvimento de firmware (sistemas baremetal e baseados em RTOS) e Linux Embarcado. Atualmente sou administrador do site Embarcados, trabalho num fabricante de Set-Top Box e atuo como consultor/desenvolvedor na área de sistemas embarcados.

13
Deixe um comentário

avatar
 
10 Comment threads
3 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
3 Comment authors
Pedro NetoHenrique RossiMarcelo JoAlgoritmos DSP com a placa STM32F4Discovery - Parte IGNU ARM Cross-toolchain – Eclipse + FreeRTOS + GCC - Parte 2 Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Pedro Neto
Visitante
Pedro Neto

Henrique, o que separa uma decisão de usar ou não S.O. para embarcados? A casos que são bem claros, mas outros que gera uma "nuvem" de dúvidas

Henrique Rossi
Visitante

Olá Pedro,

Entendo a sua dúvida. Basicamente me pergunto: "O sistema possui alguma restrição forte que precise de uma garantia de execução num determinado período?"

Se a resposta for positiva, faça uso de um RTOS. Se não, pondere. Uma máquina de estado bem feita pode resolver seu problema. Mas precisa tomar conta do processamento colaborativo gerado.

O uso de um RTOS facilita o entendimento do código, na minha opinião, pois torna o processamento linear. Já o com máquina de estado torna-se mais disperso.

Espero tê-lo ajudado. Abraços.

Pedro Neto
Visitante
Pedro Neto

Obrigado!!!

trackback

[…] GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 1 » 12-03-2014 […]

trackback

[…] GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 1 […]

trackback

[…] GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 1 […]

trackback

[...] GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 1 [...]

trackback

[...] GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 1 [...]

trackback

[...] primeira parte deste artigo foi responsável por introduzir o sistema operacional de tempo-real FreeRTOS, [...]

trackback

[...] o projeto de exemplo do FreeRTOS apresentado num post anterior da série. É necessário realizar o download dos arquivos desse projeto aqui. Use a pasta [...]

trackback

[...] GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery – Parte 1 [...]

Marcelo Jo
Visitante
Marcelo Jo

Henrique, tua série de posts tão ficando show!

Henrique Rossi
Visitante

Muito obrigado Marcelo! O próximo da série será o uso do Eclipse para brincarmos com a placa...

Grande abraço!