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

FreeRTOS 8 bare-metal

A primeira parte deste artigo foi responsável por introduzir o sistema operacional de tempo-real FreeRTOS, caminhando um pouco pela sua estrutura de arquivos. Agora, nesta segunda parte, é abordada de forma prática os passos necessários para a migração da aplicação bare-metal para a sua versão baseada nesse sistema operacional. E agora, como começo a minha aplicação?

 

Pode-se utilizar (aliás, é aconselhado!) um dos projetos de demonstração oferecidos na pasta FreeRTOS/Demo, separados por arquitetura e compilador, como mostrado abaixo. Inicie usando uma aplicação de demonstração para garantir a sua correta compilação e, de forma incremental, substitua os arquivos do projeto exemplo por arquivos da aplicação final.

 

 

Para começar a trabalhar minimamente com o FreeRTOS, vamos entender como deve ser feita a migração da aplicação bare-metal que pisca leds no kit STM32F4Discovery, usada nos posts anteriores da série, para a sua versão baseada em RTOS. Esse processo já foi realizado e o novo projeto foi disponibilizado no GitHub. Execute o seguinte comando para obtê-lo:

 

Obs: Lembre-se que no primeiro post da série GNU ARM Cross-toolchain foi apresentada a organização do ambiente de desenvolvimento para os nossos projetos. Vale a pena seguir seus passos!

 

 

O conteúdo da pasta stm32f4-discovery-freertos/hello_world, que contém os arquivos do projeto, é exibido abaixo:

 

  

Foram utilizados os mesmos arquivos da versão bare-metal do projeto. No entanto alguns pontos precisaram ser modificados, como é detalhado a seguir.

 

 

Anatomia de um projeto com FreeRTOS

 

Uma aplicação baseada no FreeRTOS é iniciada da mesma forma que uma aplicação bare-metal. Desde o reset até a chamada à função main(), o processo é o mesmo. Deve ser inicializado o ambiente de runtime da biblioteca C, configurada a pilha do sistema e inicializado o hardware utilizado. Em seguida deve ser criada pelo menos uma tarefa e ser chamada a função vTaskStartScheduler(), que entrega o controle da aplicação ao sistema operacional. Em seguida as tarefas são executadas de acordo com as suas prioridades.

 

Para que essa dinâmica seja possível na aplicação de pisca-leds, são necessárias as seguintes modificações:

  

  • adicionar os arquivos-fonte do FreeRTOS ao projeto;
  • informar os diretórios dos arquivos de cabeçalho do FreeRTOS;
  • adicionar o arquivo FreeRTOSConfig.h ao projeto;
  • configurar a tabela de vetores de exceções/interrupções;
  • criar uma tarefa e inicializar o kernel.

 

Arquivos-fonte

 

O FreeRTOS, como explicado anteriormente, é composto por alguns arquivos que implementam o kernel e os serviços oferecidos pelo sistema operacional. Esses arquivos, listados abaixo, devem ser adicionados ao projeto, de forma que sejam compilados juntamente com todos os arquivos.

 

  • FreeRTOS/Source/tasks.c;
  • FreeRTOS/Source/queue.c;
  • FreeRTOS/Source/list.c;
  • FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c;
  • FreeRTOS/Source/portable/MemMang/heap_2.c.

 

 

 

Caso seja necessário adicionar algum serviço do FreeRTOS à aplicação, seguem as opções oferecidas pelo sistema operacional e seus respectivos arquivos que devem ser adicionados ao projeto:

 

  • Software timer: FreeRTOS/Source/timers.c;
  • Event groups: FreeRTOS/Source/event_groups.c;
  • Co-routines: FreeRTOS/Source/croutine.c.

 

 

Arquivos de cabeçalho

 

Alguns diretórios devem ser incluídos no caminho de procura de arquivos de cabeçalho do projeto. Dentre esses, pode-se citar:

 

  • FreeRTOS/Source/include;
  • FreeRTOS/Source/portable/GCC/ARM_CM4F.

 

 

 

Configuração do FreeRTOS - FreeRTOSConfig.h

 

Existe um arquivo de configuração do sistema operacional, chamado FreeRTOSConfig.h, que ajusta alguns parâmetros do kernel do FreeRTOS e habilita/desabilita alguns serviços, de acordo com a necessidade da aplicação que está sendo desenvolvida. É possível uma aplicação, por exemplo, fazer uso de event groups e possuir um tamanho de heap igual a 0x4000 bytes, ao passo que em outro projeto sejam utilizadas co-routines e faça uso de um heap de 0x2000 bytes. Também, como exemplo, nesse mesmo arquivo é habilitada ou desabilitada a preempção do scheduler. Como se trata de um arquivo específico da aplicação, ele deve estar localizado fora dos diretórios do sistema operacional. Sendo assim, tal caminho escolhido também deve ser adicionado ao projeto.

 

Tabela dos vetores de exceções/interrupções

 

Outro detalhe fundamental para o uso do FreeRTOS é a adaptação do vetor de exceções do microcontrolador. O core ARM Cortex-M3/4 contém, dentre muitos outros módulos, um controlador de exceções/interrupções chamado NVIC (Nested Vectored Interrupt Controller). Dentre as suas características, oferece tratamento de exceção/interrupção vetorizado. Isso significa que o processador busca o vetor correspondente à exceção ativa sem a necessidade de algum software calcular o endereço do handler da correspondente exceção. Ao contrário do que acontece com micro-processadores ARM clássicos, o NVIC obtém tal valor por meio de hardware, tendo como dados a posição inicial da tabela de vetores de exceções e o código da exceção. A localização da posição inicial dessa tabela, que é implementada como um array de words de 32 bits, é configurada por padrão no endereço 0x0 do mapa de memória do micro-processador, mas pode ser alterada em runtime. Dessa forma, a cada 4 bytes dentro dessa tabela de vetores é especificado o endereço de um handler para a respectiva exceção.

 

Algumas exceções do core ARM Cortex-M3/4 são tratadas pelo kernel do FreeRTOS, cujos handlers estão implementados na camada portable do sistema operacional. Veja a seguir quais são essas exceções.

 

SysTick timer

 

Todo RTOS faz uso de um timer periódico para gerenciamento do tick do scheduler. O core ARM Cortex-M3/4 oferece um timer dedicado para essa função, chamado de SysTick timer, não sendo necessário utilizar um periférico de timer genérico para essa função. É a partir da exceção causada pelo timeout desse timer que o kernel trata todo o gerenciamento de tempo do sistema, usando o tick do scheduler como parâmetro, e força a troca de contexto. Esse processo é iniciado gerando uma exceção de PendSV via software, como mostrado abaixo.

 

 

PendSV

 

PendSV (Pended Service Call) é um tipo de exceção muito importante para suporte de operações de sistemas operacionais. Setando o bit 28, chamado de PENDSVSET, no registrador ICSR (Interrupt control and state register) do microcontrolador STM32F4xx, é indicado o estado pending da exceção PendSV para o NVIC. Assim que nenhuma exceção de maior prioridade que a PendSV estiver ativa, esta é atendida e seu handler é chamado, xPortPendSVHandler(), indicado na tabela de vetores do micro-processador. Veja abaixo o seu código:

 

  

Essa exceção é responsável por realizar a troca de contexto do sistema, fazendo com que o scheduler substitua a tarefa sendo executada no momento pela tarefa de maior prioridade pronta para ser executada.

 

SVC

 

Assim como a exceção PendSV, a SVC (Supervisor Call) interpreta um papel fundamental nas implementações de sistemas operacionais. Essa exceção é causada pela instrução SVC, cujo handler é executado logo após esta chamada, a não ser que uma outra exceção de maior prioridade aconteça ao mesmo tempo.

 

Em muitos sistemas operacionais, o uso de Supervisor Call é utilizado como API para permitir que tarefas acessem recursos do sistema, fazendo uma ligação entre user space e kernel space. O FreeRTOS usa esse mecanismo, mas somente para executar a primeira tarefa do sistema, por meio da função prvPortStartFirstTask(), onde é feita a chamada SVC para o serviço número 0 (zero), como mostrado abaixo.

 

 

 

 Criação de uma tarefa e inicialização do kernel

 

Agora resta somente mais um passo! Precisa ser criada uma tarefa, por meio da API do FreeRTOS, usando a função xTaskCreate(), e inicializar o kernel com a chamada à função vTaskStartScheduler().

 

Na aplicação disponibilizada foi criada uma tarefa para executar exatamente a mesma função da aplicação bare-metal estudada até então: acender os leds da placa STM32F4Discovery de forma sequencial. Segue parte do código da aplicação:

 

 

Pronto! Agora a aplicação bare-metal está migrada para uma versão com o FreeRTOS. Vamos compilá-la e depurá-la com o que aprendemos até aqui? Conecte a sua placa STM32F4Discovery no seu PC com o cabo USB e execute os seguintes comandos para compilar a aplicação e iniciar o servidor GDB, o OpenOCD:

 

 

As mensagens abaixo devem ser exibidas. Neste momento o OpenOCD já iniciou o seu servidor GDB e está aguardando comandos do aplicativo cliente.

 

 

O passo seguinte é, em outro prompt do shell, inicializar o cliente GDB, indicar a aplicação a ser depurada e executar comandos de gravação/depuração no prompt do cliente GDB, como mostrado abaixo:

 

 

Como esperado, os leds acedem da mesma forma que aconteceu com a aplicação bare-metal. Verificamos que o breakpoint é ativado na primeira e nas seguintes execuções do loop da tarefa leds_blink_task. Agora é só criar mais tarefas para a brincadeira ficar mais divertida. Isso fica a gosto do cliente! E a função main(), não é mais executada? Não! Todo o controle de qual tarefa a ser executada está sob a responsabilidade do scheduler do FreeRTOS. Nos momentos em que não existem tarefas com alguma atividade a ser realizada, como acontece no momento em que a função vTaskDelay() é chamada, a tarefa Idle do RTOS é executada. Mas o que ganhamos com isso? Nos próximos posts explicaremos as diferenças e, principalmente, o que é oferecido de vantagem com essa nova implementação. Aguardem!

Outros artigos da série

<< GNU ARM Cross-toolchain – FreeRTOS + GCC + STM32F4Discovery - Parte 1GNU ARM Cross-toolchain – Eclipse + FreeRTOS + GCC - Parte 1 >>
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.

21
Deixe um comentário

avatar
 
10 Comment threads
11 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
5 Comment authors
Vinicius MacielWellington MateusRafael DiasHenrique RossiEduardo Scherrer Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Wellington Mateus
Visitante
Wellington Mateus

Boa tarde Henrique!!!!

Como fazer o upload para o microcontrolador?
Li todos os artigos, mas agora como faço o upload?

Vinicius Maciel
Visitante
vinifr

Ola, o upload é feito quando você digita: arm-none-eabi-gdb build/hello_world.elf, os outros comandos e depois o comando load

Henrique Rossi
Visitante

Olá Wellington,

Como o Vinicius disse, a gravação no microcontrolador acontece no comando load, que carrega o binário hello_world.elf na memória Flash.

Abraços,
Henrique

trackback

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

Rafael Dias
Visitante
Rafael Dias

Opa! Consegui implementar muita coisa usando o FreeRTOS no projeto que estou desenvolvendo usando um uC Tiva TM4C123G. Demorei um pouco para entender como se configurar os parâmetros necessários no arquivo FreeRTOSConfig.h. O restante, saiu funcionando quase que direto. Estou usando semáforos, filas e, claro, tasks. O que achei mais legal é que me acelerou muito o desenvolvimento, principalmente pois eu nunca havia trabalhado com RTOSses e sei do trabalho que eu teria para fazer a mesma coisa usando uma abordagem bare metal. Acho que um trabalho futuro será determinar os valores das prioridades das tasks e determinar o quanto… Leia mais »

Henrique Rossi
Visitante

Muito legal Rafael! Pretendemos disponibilizar esse tipo de conteúdo no Embarcados. Vamos acelerar o processo! E muito obrigado pelos seus comentários! 🙂

Abraços!

Rafael Dias
Visitante
Rafael Dias

Hoje me aconteceu uma coisa curiosa. Uma das interfaces que estou desenvolvendo aqui é uma comunicação RS-485 entre dois sistemas. Como estou em uma rede RS-485, tenho que controlar a direção do canal de comunicação através de um pino DE (Data Enable). Bom, esse controle eu deixei a cargo de um timer. Fiz algo assim (vou colar partes do código para dar uma idéia): http://pastebin.com/1aKLgvx6 Bom, na função RS485Open eu crio um timer e o utilizo assim que envio os dados pela porta serial, utilizando a função RS485Write. Assim que os dados são enviados, o timer é iniciado e deveria… Leia mais »

Henrique Rossi
Visitante

Olá Rafael, tudo bem? Desculpa pela demora na resposta...eu vi a sua pergunta esses dias rs Na sua chamada a xTimerCreate, xTimerPeriod = 2 / portTICK_RATE_MS ajusta o timer para um período de 2 ms, não 1 ms. E a prioridade do serviço de timer, dada pela constante configTIMER_TASK_PRIORITY, deve ser ajustada para que justamente o período de timeout do respectivo timer seja o mais próximo do ajustado. Provavelmente alguma tarefa de alta prioridade está "segurando" o processamento do escalonador, e a tarefa do timer não esteja sendo executada no seu devido tempo. Tente aumentar gradativamente a prioridade do timer… Leia mais »

trackback

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

trackback

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

trackback

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

trackback

[...] 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 [...]

trackback

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

trackback

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

Eduardo Scherrer
Visitante
Eduardo C. Scherrer

Olá Henrique,

Agora estou com uma placa em mãos.

Passei por todos os post relacionados, e todos rodaram muito bem.

Como já onvi falarem (se não me engano, o próprio Sérgio Prado no blog), engenheiros de software, são pessoas extremamente ansiosas por botar a mão na massa.
Quando chegam os próximos posts?

Serão abordados mais detalhes sobre o FreeRTOS? As demais funcionalidades? Mais exemplos? Como canais de comunicação? Compartilhamento de recursos? Uso de interrupções?

E como sempre, excelente post.

Abraço.

Eduardo Scherrer

Henrique Rossi
Visitante

Olá Eduardo!

Agora não tem desculpa para não usar a placa!! 😉

Essa série não vai parar por aqui! Teremos um post de Eclipse, e em seguida posts teóricos e práticos sobre o FreeRTOS, tais como: sincronização entre tarefas, compartilhamento de recursos, redução do consumo de energia gerado, e outros. Vamos estudar a possibilidade de serem usados todos os canais de comunicação da placa. Pretendemos ter um post dessa série a cada uma ou duas semanas.

Muito obrigado pelos elogios e acompanhamento do site!! Fique ligado! 🙂

Abraços!

Eduardo Scherrer
Visitante
Eduardo C. Scherrer

Boa noite Henrique,

Muito bom hein. Agora fiquei mais empolgado.

Eu cheguei a comprar a documentação para o uC da NXP. Mas só na teoria não vira, preciso de exemplos para firmar mais os conceitos.

Abraço e obrigado.

Eduardo Scherrer

Henrique Rossi
Visitante

Oi Eduardo, boa noite!

Tentaremos trabalhar com outros microcontroladores também, não sabemos se nessa série. Vamos ver como vai ficar! Mas com relação a FreeRTOS teremos mais conteúdo.

Eu que agradeço! Abraços

Rafael Dias
Visitante
Rafael Dias

Esta semana eu comecei a trabalhar em um projeto utilizando microcontroladores da Texas (lm4f232h5qd). Como estou com liberdade de usar qualquer ferramenta, vou partir para o uso do FreeRTOS.

Acho que dará para brincar um pouco. =P

Henrique Rossi
Visitante

A Tivaware deve ajudar no desenvolvimento...deve ser bem legal trabalhar com esses microcontroladores. Mande notícias!! 🙂

Abraços!

Rafael Dias
Visitante
Rafael Dias

Eu ainda estou aprendendo a trabalhar com a tiviaware. Já gostei pois é mais documentado do que a StdPeripheralLibrary da ST.

Vamo que vamo!