O que é kconfig?
Os projetos de esp32, possuem um ou mais arquivos kconfig, em sua estrutura, porem esse tipo arquivo foi herdado do kenel linux, com intuito de torna-lo altamente personalizável, fornecendo as configurações de em forma de definições para os módulos do kernel.
Para projetos utilizando o esp32, o kconfig tem basicamente o mesmo intuito, ele fornece as classes as definições base do projeto, isso tudo em tempo de compilação. Para a demonstração foi fornecido um contexto geral do arquivo, desde sua criação até sua utilização.
Criando o kconfig no esp32
Para o exemplo, foi utilizado como projeto base, um template disponibilizado pela fabricante Espressif Systems.
Para o exemplo desenvolvemos um menu com o nome de Configurações do projeto teste, onde foi utilizado no desenvolvimento os seguintes comandos:
Atributos da configuração GPIO_LED_2
Na parte inferior da tela temos o menu de navegação do menuconfig, para entrar nos submenus basta utilizar as teclas ->, espaço ou enter . Na Figura 3 será apresentado o item de configuração “GPIO do led 2”, como denominado no exemplo codificado.
No exemplo definimos um range de valores validos para a aplicação (de 1 a 10), para mostrar essa funcionalidade foi adicionado um valor fora desse intervalo, a Figura 4 apresenta a mensagem resultante desse teste.
Como já comentado acima a tecla “?” quando pressionada abrira uma tela de ajuda atrelada ao item onde esta sendo feita as alterações, contendo a mensagem de texto configurada no atributo help. A Figura 5 apresenta a tela de help.
É possível alterar o tipo de entrada para outros tipos além de int, como por exemplo uma entrada hexadecimal ou uma string. Abaixo utilizamos uma entrada em hexadecimal, para representar, caso deseje saber todos os tipos recomenda-se que seja consultada a documentação do kernel.
Logo abaixo da entrada config REGISTRO_1 encontram-se seus atributos:
O arquivo kconfig esp32 possui outras entradas como comentado acima , para uma nova demonstração iremos utilizar a atributo choice, que basicamente permite a escolha entre uma ou mais configuração, como um menu de opções. Abaixo temos um exemplo onde possuímos duas opções dentro da configuração, “Teste” e “Aplicação”.
Nota-se que as configurações precisam ser dos mesmo tipo, como MODO_DE_APLICACAO e MODO_DE_TESTE, a Figura 6 apresenta o menu após a inserção do choice.
As configurações podem ter dependências entre elas, para isso é especificado com o atributo depends on, onde em sua frente é passado todas as dependências da configuração.
Notamos que no código a opção “pino do sensor” depende de SENSOR_STATUS estar habilitado, caso queira inverter a ordem basta adicionar o sinal de negação ! ao início de SENSOR_STATUS (depends on !SENSOR_STATUS).
Ao marcar a caixa de seleção a opção “pino de sensor” é apresentada no menu, como mostrado na Figura 9.
O atributo depends on pode ser utilizado em comentários, menus, entre outros. Para mais informações consulte a documentação do kernel.
O arquivo kconfig no esp32 também possui suporte a logicas de programação. como a lógica if.
O exemplo possui duas entradas PIN_SENSOR_1 e PIN_SENSOR_2 que são do tipo int, notamos que a segunda entrada possui um atributo prompt, e utiliza da lógica if, sendo assim a opção prompt só estará visível se o valor do primeiro argumento for menor do que 10 (PINO_SENSOR_1 < 10).
O kconfig no esp32 possui varios tipos de menu, atributos e lógicas além das apresentadas aqui. Para os exemplos utilizamos a extensão “.projbuild”, porém podemos criar o arquivo em outros formatos, isso irá depender da aplicação em que será utilizado.
Após ser feita a configuração do modo de operação através da ferramenta menuconfig, foi realizada a compilação do código, para isso, basta executar o comando "make build" ou "idf.py build".
No código temos a inclusão do arquivo “sdkconfig.h”, ele é gerado após a compilação e contém todas as definições do projeto, seja ela de hardware ou de aplicação, notamos que nesse arquivo as definições utilizam o prefixo “CONFIG_”. A Figura 12 apresenta um trecho do arquivo gerado após a compilação, destacando a definição gerada pelo nosso exemplo.
A Figura 1 apresenta os arquivos do projeto base, nela notamos a presença de um arquivo denominado Kconfig.projbuild, localizado na pasta main do projeto.
Para o exemplo desenvolvemos um menu com o nome de Configurações do projeto teste, onde foi utilizado no desenvolvimento os seguintes comandos:
- menu : é o atributo do menu principal de um bloco(conjunto) de configurações, onde tem seu fim indicado pela palavra endmenu.
- config : atributo de entrada(s) de dados para configuração (atributo do menu), cada entrada é definido por uma configuração distinta.
O exemplo abaixo é de um menu com opção de configuração, para valida-lo abra um editor de sua preferência (recomenda-se o esp ide) e edite o Kconfig.projbuild.
```c
# kconfig esp32 exemplo base
menu "Configurações do projeto teste"
config GPIO_LED_2
int "GPIO do led 2"
default 10
range 1 10
help
Essa opção possibilita a configuração do pino
endmenu
```
Podemos notar que a frente do atributo config temos o nome GPIO_LED_2 que é atribuído a essa configuração, esse nome na etapa de compilação sera transformado em definições presentes no arquivo sdkconfig.h
- int : define que a entrada de dados é um valor do tipo inteiro, logo em seguida temos o nome que será apresentado no menu, no exemplo GPIO do led 2.
- default : valor padrão da entrada de dados.
- range : intervalo para valores válidos (no exemplo entre 1 e 10).
- help : mensagem de ajuda que será apresentada no menuconfig quando pressionado '?' na configuração.
Figura 2 – Menu principal (kconfig esp32). |
Figura 3 – Entrada de dados valor inteiro (kconfig esp32). |
Figura 4 – Valor invalido (kconfig esp32). |
Figura 5 – Tela de help (kconfig esp32). |
```c
# kconfig esp32 exemplo hexadecimal
menu "Configurações do projeto teste"
config REGISTRO_1
hex
prompt "Valor do registro"
default 0x05
help
valor do registro 1
endmenu
```
- hex: input do tipo hexadecimal.
- prompt : mensagem apresentada no campo de input de REGISTRO_1.
O atributo prompt é transparente, ou seja ao especificarmos com aspas a frente do tipo configuração como no exemplo base não há necessidade de utilizá-lo.
```c
# kconfig esp32 exemplo prompt
menu "Configurações do projeto teste"
config REGISTRO_1
hex
prompt "Valor do registro 1"
config REGISTRO_2
hex "Valor do registro 2"
endmenu
```
```c
# kconfig esp32 exemplo base
menu "Configurações do projeto teste"
choice MODO_OPERACAO_FW
prompt "Modo de operação do firmware"
default MODO_DE_APLICACAO
help
Configuração do modo de operação do FW.
config MODO_DE_APLICACAO
bool "Aplicação"
config MODO_DE_TESTE
bool "Teste"
endchoice
endmenu
```
Ao entrar no submenu da opção será apresentado todas as opções definidas dentro do choice como mostra a Figura 7.
```c
# kconfig esp32 exemplo depends
menu "Configurações do projeto teste"
config SENSOR_STATUS
bool "Habilita o sensor"
default "n"
help
Selecione esta opção para habilitar o sensor.
config SENSOR_PINO
int "pino do sensor"
default 10
depends on SENSOR_STATUS
help
Pino do sensor.
endmenu
```
Figura 8 – Checkbox de configuração (kconfig esp32). |
Figura 9 – Campo com dependência (kconfig esp32). |
O arquivo kconfig no esp32 também possui suporte a logicas de programação. como a lógica if.
```c
# kconfig esp32 exemplo if
menu "Configurações do projeto teste"
config PINO_SENSOR_1
int "pino do sensor 1"
default 15
help
Pino do sensor 1.
config PINO_SENSOR_2
int
prompt "pino do sensor 2" if PINO_SENSOR_1 < 10
default 10
help
Pino do sensor 2.
endmenu
```
Figura 10 – Entrada de dados do sensor 1 (kconfig esp32). |
Figura 11 – Lógica if no campo pino do sensor 2 (kconfig esp32). |
Implementação nos projetos de esp32
Abaixo teremos um exemplo de implementação em C/C++ de utilização de kconfig no esp32, para essa demonstração, utilizaremos o exemplo apresentado nas figuras 6 e 7.Após ser feita a configuração do modo de operação através da ferramenta menuconfig, foi realizada a compilação do código, para isso, basta executar o comando "make build" ou "idf.py build".
```c
// kconfig esp32 exemplo de implementação
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "sdkconfig.h"
void app_main(void)
{
while (1) {
#ifdef CONFIG_MODO_DE_APLICACAO
//executar o firmware em modo de aplicação
#else
//executar o firmware em modo de teste
#endif
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
```
Figura 12 – Arquivo sdkconfig.h (kconfig esp32). |
Conclusão
A utilização do kconfig customizado é uma boa prática em projetos, visto que deixar as configurações escritas à mão dentro do código é menos rastreável e menos organizado. O artigo teve um intuito introdutório, recomenda-se que leia as documentações para utilizar a ferramenta com todos os recursos disponíveis.Para complementar o conteúdo leia também o post sobre sdkconfig.