打印
[开发工具]

利用 Kconfig 实现APM32项目的可视化配置

[复制链接]
91|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
susutata|  楼主 | 2024-11-10 20:20 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 susutata 于 2024-11-10 20:20 编辑

#申请原创# @21小跑堂


利用 Kconfig 实现APM32项目的可视化配置


## 01 前言
最早接触到 `Kconfig` 文件是在使用 `ESP32` 的时候,`ESP-IDF` 的配置文件就是使用 `Kconfig` 文件来进行配置的。后来发现在 `linux` 、`RT-Thread` 和 `Zephyr` 等项目中也有使用到 `Kconfig` 来进行项目配置。可以看出 `Kconfig` 在嵌入式领域大型项目中有着广泛的应用。

从实际项目开发的角度来看,会经常需去使能或者关闭某些功能、修改一些参数,这些参数可能会影响到代码的编译、运行、功能等。如果这些参数是直接写在代码中的,那么每次修改参数都需要修改代码,然后重新编译,这样的效率是非常低的。而使用 `Kconfig` 文件来进行配置,可以在不修改代码的情况下,通过配置文件来修改参数,然后重新编译即可。


这里举两个使用场景来说明如果没有用 `Kconfig` 文件来进行配置,一般会怎么做。

### 预编译场景
在命令行中通过 `-D` 宏定义来控制代码的编译,例如:
gcc -DCONFIG_FEATURE_A -DCONFIG_PARAM_B=100

#define CONFIG_FEATURE_A
#define CONFIG_PARAM_B 100

### 代码条件编译场景
在代码中通过 `#ifdef` 来控制代码的编译,例如:
#define CONFIG_FEATURE_A

#ifdef CONFIG_FEATURE_A
    // do something
#endif
上面的两种方式在小型项目中还是可以接受的,但是在大型项目中,当参数很多时,这样的方式就会变得非常不方便,且不直观。而 `Kconfig` 就是为了解决这个问题而生的工具。

## 02 Kconfig 环境搭建
推荐使用 `python` 来安装 [Kconfiglib](https://pypi.org/project/kconfiglib) ,同时还要用到 `menuconfig` 来进行可视化配置。要注意的是,在 `windows` 下使用 `menuconfig` 还需要安装 `curses` 库。
python -m pip install windows-curses
python -m pip install kconfiglib

安装完成后,可以使用以下命令来检查 `Kconfig` 和 `menuconfig` 的安装情况:
PS E:\workspaces\Project\github\embedded\omni-sdk> pip show Kconfiglib
Name: kconfiglib
Version: 14.1.0
Summary: A flexible Python Kconfig implementation
Home-page: https://github.com/ulfalizer/Kconfiglib
Author: Ulf "Ulfalizer" Magnusson
Author-email: ulfalizer@gmail.com
License: ISC
Location: c:\users\lin\appdata\local\programs\python\python39\lib\site-packages
Requires:
Required-by:
PS E:\workspaces\Project\github\embedded\omni-sdk> menuconfig -h
usage: menuconfig [-h] [KCONFIG]

Overview
========

A curses-based Python 2/3 menuconfig implementation. The interface should feel
familiar to people used to mconf ('make menuconfig').

Supports the same keys as mconf, and also supports a set of keybindings
inspired by Vi:

  J/K     : Down/Up
  L       : Enter menu/Toggle item
  H       : Leave menu
  Ctrl-D/U: Page Down/Page Up
  G/End   : Jump to end of list
  g/Home  : Jump to beginning of list

环境搭建完成后,就可以利用 `Kconfig` 来生成 `.config` 配置文件,但是这个文件的内容还需要转换为宏定义才能被 C 语言项目用来进行配置。

`.config` 文件格式:
#
# Components
#
# CONFIG_COMPONENT_CONSOLE is not set
# CONFIG_COMPONENT_CHERRYUSB is not set
# end of Components

# CONFIG_OMNI_DRIVER is not set

#
# Libraries
#
# CONFIG_U8G2 is not set
# CONFIG_SEGGER_RTT is not set
# CONFIG_SHELL_LETTER is not set
CONFIG_RTOS_NONE=y
# CONFIG_RTOS_CMSIS_RTX is not set
# CONFIG_RTOS_CMSIS_FREERTOS is not set
# CONFIG_RTOS_THREADX is not set
CONFIG_USB_NONE=y
# CONFIG_USB_CHERRYUSB is not set
# CONFIG_USB_STM32 is not set
# end of Libraries

可以编写一个 `Python` 脚本调用 `class Kconfig` 中的 `write_autoconf()` 方法来生成 `autoconf.h` 文件。推荐直接使用 `zephyr` 项目中的 `kconfig.py` 脚本。
- `kconfig_file`:顶层 `Kconfig` 文件的路径
- `config_out`:生成 `.config` 文件的路径
- `header_out`:生成 `xxx.h` C 语言头文件的路径
- `kconfig_list_out`:日志输出文件的路径
- `config_in`:配置片段文件



## 03 Kconfig 基本应用
这里不展开介绍 `Kconfig` 的语法,感兴趣的读者可以查看 `linux` 的 [Kconfig-language](https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt) 文档。

下面以搭建 `APM32` 项目为例,展示如何使用 `CMake` + `ARM GCC` + `Kconfig` 来进行项目配置。在开始之前,需要先安装 `CMake` 和 `ARM GCC` 工具链。之前的文章中已经介绍过如何安装这两个工具,这里就不再赘述。

下载 [apm32-kconfig-example](https://github.com/LuckkMaker/apm32-kconfig-example) 后打开目录可以找到顶层的 `Kconfig` 文件。

`Kconfig` :
配置项目名称、版本、`LED` 闪烁、闪烁间隔等配置。
mainmenu "APM32 Project Configuration"

config PROJECT_NAME
    string
    prompt "Project Name"
    default "apm32-project"
    help
      "The name of the project. This will be used to name the output files."

config PROJECT_VERSION
    string
    prompt "Project Version"
    default "0.0.1"
    help
      "The version of the project."

choice
    prompt "LED Toggle"
    default LED1_TOGGLE

config LED1_TOGGLE
    bool "LED1"
    help
      "Enable LED toggle functionality."

config LED2_TOGGLE
    bool "LED2"
    help
      "Enable LED toggle functionality."

endchoice

config LED_TOGGLE_INTERVAL
    int
    prompt "LED Toggle Interval"
    default 500
    help
      "The interval at which LED will toggle."

`main.c` :
引用 `autoconf.h` 文件,根据配置文件中的配置来控制代码 `LED` 的闪烁及闪烁间隔。
#include "main.h"
#include "autoconf.h"
int main(void)
{
    /* Device configuration */
    DAL_DeviceConfig();

    /* Infinite loop */
    while (1)
    {
#if defined(CONFIG_LED1_TOGGLE)
        DAL_GPIO_TogglePin(GPIOE, GPIO_PIN_5);
#else
        DAL_GPIO_TogglePin(GPIOE, GPIO_PIN_6);
#endif /* CONFIG_LED1_TOGGLE */
        DAL_Delay(CONFIG_LED_TOGGLE_INTERVAL);
    }
}

在终端输入 `menuconfig` 命令,可以看到如下界面:


如果不更改配置可以输入 `Q` 退出并保存配置,`Kconfig` 文件目录下会生成 `.config` 文件,内容如下:
CONFIG_PROJECT_NAME="apm32-project"
CONFIG_PROJECT_VERSION="0.0.1"
CONFIG_LED1_TOGGLE=y
# CONFIG_LED2_TOGGLE is not set
CONFIG_LED_TOGGLE_INTERVAL=500

有了该文件后,就可以使用 `Python` 脚本来生成 `autoconf.h` 文件,命令如下:
python tools/python/kconfig.py Kconfig .config autoconf.h kconfigLog.txt .config


生成的 `autoconf.h` 文件内容如下:

#define CONFIG_PROJECT_NAME "apm32-project"
#define CONFIG_PROJECT_VERSION "0.0.1"
#define CONFIG_LED1_TOGGLE 1
#define CONFIG_LED_TOGGLE_INTERVAL 500
这样就可以在代码中使用这些宏定义来控制代码的编译。

## 04 Kconfig 进阶应用
当项目越来越大时,可能会有多个`App` 例程共用一个模块但配置需求又不一样的情况。还是例如上面的例子,如果有两个 `App` 例程,一个需要 `LED1` 闪烁,另一个需要 `LED2` 闪烁,这时就需要用到 `prj.conf` 文件来进行配置。
-app1
  -prj.conf
  -main.c

-app2
    -prj.conf
    -main.c

-Kconfig


`app1/prj.conf` :

CONFIG_LED2_TOGGLE=y
CONFIG_LED_TOGGLE_INTERVAL=500


`app2/prj.conf` :

CONFIG_LED1_TOGGLE=y
CONFIG_LED_TOGGLE_INTERVAL=1000

在 `apm32-kconfig-example` 项目中使用下面的命令来根据 `prj.conf` 文件生成 `autoconf.h` 文件:
python tools/python/kconfig.py --handwritten-input-configs Kconfig .config autoconf.h kconfigLog.txt .config application/prj.conf


`prj.conf` :

CONFIG_LED2_TOGGLE=y
CONFIG_LED_TOGGLE_INTERVAL=500

`autoconf.h` :
#define CONFIG_PROJECT_NAME "apm32-project"
#define CONFIG_PROJECT_VERSION "0.0.1"
#define CONFIG_LED2_TOGGLE 1
#define CONFIG_LED_TOGGLE_INTERVAL 500
这样就可以根据不同的 `App` 例程来生成不同的 `autoconf.h` 文件,从而实现不同的配置。

本文使用的例子可以在 [apm32-kconfig-example](https://github.com/LuckkMaker/apm32-kconfig-example) 获取。

想要更多构建应用例子可以在 [omni-sdk](https://github.com/LuckkMaker/omni-sdk) 找到。



使用特权

评论回复
沙发
问天少年| | 2024-11-12 21:54 | 只看该作者
这个可视化体现在哪里啊,每看懂

使用特权

评论回复
板凳
susutata|  楼主 | 2024-11-13 08:54 | 只看该作者
问天少年 发表于 2024-11-12 21:54
这个可视化体现在哪里啊,每看懂

kconfig 写完后,用 menuconfig 指令就能从终端拉起可视化配置界面哈

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

31

帖子

3

粉丝