Qual o footprint de memória do FreeRTOS?
- por Sergio Prado
Esta é uma pergunta frequente. E a resposta depende de diversos fatores, incluindo a configuração do FreeRTOS, o compilador utilizado, a plataforma de hardware e as características da sua aplicação.
Segundo o FAQ oficial do projeto, o uso de flash pode variar de 5KB a 10KB, e o uso de RAM do escalonador gira em torno de 250 bytes. Claro que não estão inclusos aqui a memória RAM alocada para cada componente criado pela aplicação (tarefa, queue, semáforo, timer, etc).
Mas nada melhor do que tirar nossas próprias conclusões, não é verdade? :)
Fiz alguns testes utilizando o kit de desenvolvimento FRDM-KL46Z, um ARM Cortex-M0 de 48MHz com 256KB de flash e 32KB de SRAM.
Criei um projeto para compilar uma aplicação enxuta com o FreeRTOS, utilizando um toolchain baseado no GCC mantido pelo próprio pessoal da ARM.
O projeto é composto por uma aplicação simples com duas tarefas (80 words de stack alocados para cada tarefa) e 12KB alocados para o heap do FreeRTOS. O projeto está disponível no Github, para quem quiser dar uma olhada.
O resultado final foi este:
$ arm-none-eabi-size main.elf text data bss dec hex filename 6804 24 13544 20372 4f94 main.elf |
Em resumo, a aplicação irá consumir 6804 bytes de flash e 13568 (13544 + 24) bytes de RAM. Mas que parte deste consumo de memória vem do FreeRTOS?
Para responder esta pergunta, podemos dar uma olhada no mapa de símbolos gerado pelo compilador.
Vamos primeiro analisar o tamanho do código do FreeRTOS:
$ cat main.map | grep ".text" [...] *(.text .text.* .gnu.linkonce.t.*) .text 0x00000410 0x130 main.o .text 0x00000540 0x68 startup.o .text 0x000005a8 0x150 freertos/list.o .text 0x000006f8 0x12b4 freertos/tasks.o 0x00000cf0 vTaskSwitchContext .text 0x000019ac 0x1f4 freertos/portable/MemMang/heap_2.o .text 0x00001ba0 0x204 freertos/portable/GCC/ARM_CM0/port.o |
Podemos medir o tamanho do código do FreeRTOS, e consequentemente seu consumo de memória flash, somando individualmente o tamanho da região .text de cada arquivo-fonte do FreeRTOS, totalizando 6140 bytes na listagem acima.
Já o consumo de RAM está dividido nas seções .data (variáveis inicializadas) e .bss (variáveis não-inicializadas).
Veja no comando abaixo que são consumidos pelo FreeRTOS apenas 8 bytes na seção de variáveis inicializadas.
$ cat main.map | grep ".data" [...] *(.data .data.*) .data 0x1fffe000 0x4 freertos/portable/MemMang/heap_2.o .data 0x1fffe004 0x4 freertos/portable/GCC/ARM_CM0/port.o |
Já na seção de variáveis não-inicializadas, são consumidos 212 bytes pelo escalonador (tasks.o) e 12308 bytes pela implementação de alocação de memória utilizada no projeto de exemplo (heap_2.o).
$ *(.bss .bss.*) [...] .bss 0x1fffe008 0xd4 freertos/tasks.o .bss 0x1fffe0dc 0x3014 freertos/portable/MemMang/heap_2.o |
A implementação de alocação de memória consume bastante RAM porque ela pré-aloca um buffer de 12KB para a região de heap do FreeRTOS. Esta região será utilizada para a criação dos componentes da aplicação (tarefa, queue, semáforo, etc) e pode ser alterada conforme a necessidade através da variável configTOTAL_HEAP_SIZE no FreeRTOSConfig.h.
Sem considerar o buffer pré-alocado para o heap do FreeRTOS, temos um consumo de flash de 6140 bytes e um consumo de RAM de 220 bytes (212 + 8), valores bem próximos aos documentados no FAQ do projeto.
Claro que, para cada componente criado pela aplicação (tarefa, queue, semáforo, etc) mais memória RAM será utilizada. Por exemplo, a estrutura que armazena informações sobre as tarefas (TCB ou Task Control Block) possui um tamanho típico de 80 bytes, e para criar uma tarefa com 100 bytes de stack, serão alocados 180 bytes do heap do FreeRTOS.
Na prática, estes são valores típicos que podem depender das características da plataforma de hardware, do compilador (incluindo as flags de compilação utilizadas), configuração do FreeRTOS e dos componentes do kernel criados pela aplicação.
Conclusão? O FreeRTOS é realmente um kernel bastante enxuto e eficiente com relação ao consumo de memória RAM e flash.
A não ser que você tenha em mãos um microcontrolador de 8 bits com 2K de flash e 256 bytes de RAM, falta de memória não deve ser uma desculpa para você não utilizá-lo, principalmente pelas diversas vantagens trazidas pelo uso de um kernel de tempo real. De acordo? :)
Have fun!
Sergio Prado